{
  "openapi": "3.1.0",
  "info": {
    "title": "Anium 公開読み取り API",
    "version": "1.0.1",
    "description": "anium.jp で公開されているアニメ、シリーズ、声優、キャラクター、記事、Anium Manga の公開カタログを匿名で参照するための読み取り専用 API です。Manga は無料話リーダーのみを upstream の匿名権限で中継し、認証・購入・unlock は提供しません。"
  },
  "servers": [
    {
      "url": "https://anium.jp/api",
      "description": "本番環境"
    }
  ],
  "paths": {
    "/anime": {
      "get": {
        "summary": "アニメ作品一覧",
        "operationId": "listAnime",
        "parameters": [
          { "$ref": "#/components/parameters/Limit100" },
          { "$ref": "#/components/parameters/Offset" },
          { "name": "search", "in": "query", "schema": { "type": "string" }, "description": "作品名または制作会社名の検索語" },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["airing", "finished", "upcoming"] } },
          { "name": "type", "in": "query", "schema": { "type": "string", "enum": ["tv", "movie", "ova", "ona", "special"] } },
          { "name": "year", "in": "query", "schema": { "type": "integer" }, "description": "放送年。0 は放送年未登録" },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["score", "newest", "title", "popularity"] } }
        ],
        "responses": {
          "200": {
            "description": "作品一覧",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnimeListResponse" } } }
          },
          "400": { "description": "status、type、year、sort のいずれかが不正です", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/anime/{id}": {
      "get": {
        "summary": "アニメ作品詳細",
        "description": "数字のみの値は常に作品IDとして扱います。数字以外の既存slugは後方互換のため引き続き利用できます。数字のみのslugは /anime/by-slug/{slug} を使用してください。",
        "operationId": "getAnime",
        "parameters": [{ "$ref": "#/components/parameters/IdOrSlug" }],
        "responses": {
          "200": { "description": "作品詳細", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnimeDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/anime/by-slug/{slug}": {
      "get": {
        "summary": "アニメ作品詳細（slugを明示）",
        "description": "数字のみの既存slugを数値IDと区別して取得するための追加経路です。既存のID経路の意味は変更しません。",
        "operationId": "getAnimeBySlug",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "作品詳細", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnimeDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/series": {
      "get": {
        "summary": "シリーズ一覧",
        "operationId": "listSeries",
        "parameters": [
          { "$ref": "#/components/parameters/Limit100" },
          { "$ref": "#/components/parameters/Offset" },
          { "$ref": "#/components/parameters/Search" }
        ],
        "responses": {
          "200": { "description": "シリーズ一覧", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SeriesListResponse" } } } }
        }
      }
    },
    "/series/{slug}": {
      "get": {
        "summary": "シリーズ詳細",
        "description": "数字のみの値は常にシリーズIDとして扱います。数字以外の既存slugは後方互換のため引き続き利用できます。数字のみのslugは /series/by-slug/{slug} を使用してください。",
        "operationId": "getSeries",
        "parameters": [{ "$ref": "#/components/parameters/SlugOrId" }],
        "responses": {
          "200": { "description": "シリーズ詳細", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SeriesDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/series/by-slug/{slug}": {
      "get": {
        "summary": "シリーズ詳細（slugを明示）",
        "description": "数字のみの既存slugを数値IDと区別して取得するための追加経路です。既存のID経路の意味は変更しません。",
        "operationId": "getSeriesBySlug",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "シリーズ詳細", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SeriesDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/manga/home": {
      "get": {
        "summary": "Anium Manga 公開ホーム",
        "description": "公開ホーム情報のみ。Account/Manga の認証情報、Cookie、ライブラリ、ウォレット、unlock、購入は転送しません。",
        "operationId": "getMangaHome",
        "responses": {
          "200": { "description": "公開 Manga ホーム情報", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MangaHomeResponse" } } } },
          "502": { "description": "Mangaサービスの応答を取得できない、または形式が未対応" }
        }
      }
    },
    "/manga/titles": {
      "get": {
        "summary": "Anium Manga 公開作品一覧",
        "description": "q/genre を使う匿名の公開カタログ検索です。認証・購入情報は転送しません。",
        "operationId": "listMangaTitles",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 120 } },
          { "name": "genre", "in": "query", "schema": { "type": "string", "maxLength": 120 } }
        ],
        "responses": {
          "200": { "description": "公開 Manga 作品一覧", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MangaTitlesResponse" } } } },
          "502": { "description": "Mangaサービスの応答を取得できない、または形式が未対応" }
        }
      }
    },
    "/manga/titles/{titleId}": {
      "get": {
        "summary": "Anium Manga 公開作品詳細",
        "description": "作品情報と話一覧。話の unlock・レンタル・購入は行いません。",
        "operationId": "getMangaTitle",
        "parameters": [
          { "name": "titleId", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$" } }
        ],
        "responses": {
          "200": { "description": "公開 Manga 作品詳細", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MangaTitleDetailResponse" } } } },
          "400": { "description": "作品IDが不正です" },
          "502": { "description": "Mangaサービスの応答を取得できない、または形式が未対応" }
        }
      }
    },
    "/manga/chapters/{chapterId}/reader": {
      "get": {
        "summary": "Anium Manga 無料話リーダー",
        "description": "匿名で閲覧できる無料話だけを中継します。upstream の 401/403 はそのまま拒否し、paid chapter の unlock/購入は行いません。",
        "operationId": "getMangaChapterReader",
        "parameters": [
          { "name": "chapterId", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$" } }
        ],
        "responses": {
          "200": { "description": "匿名閲覧可能な無料話ページ情報", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MangaReaderResponse" } } } },
          "400": { "description": "話IDが不正です" },
          "401": { "description": "upstream が認証または閲覧権限を要求しました" },
          "403": { "description": "upstream が匿名閲覧を拒否しました" },
          "502": { "description": "Mangaサービスの応答を取得できない、または形式が未対応" }
        }
      }
    },
    "/books": {
      "get": {
        "summary": "公開 Books 書籍・漫画一覧",
        "description": "ログイン不要の公開カタログです。認証情報や購入情報は転送されません。",
        "operationId": "listBooks",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 120 } },
          { "name": "kind", "in": "query", "schema": { "type": "string", "maxLength": 120 } },
          { "name": "format", "in": "query", "schema": { "type": "string", "maxLength": 120 } },
          { "name": "magazine", "in": "query", "schema": { "type": "string", "maxLength": 120 } }
        ],
        "responses": {
          "200": { "description": "公開書籍オブジェクトの配列", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BooksListResponse" } } } },
          "502": { "description": "Booksサービスの応答を取得できません" }
        }
      }
    },
    "/books/featured": {
      "get": {
        "summary": "公開 Books おすすめ一覧",
        "operationId": "listFeaturedBooks",
        "responses": {
          "200": { "description": "おすすめ書籍の配列", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BooksListResponse" } } } },
          "502": { "description": "Booksサービスの応答を取得できません" }
        }
      }
    },
    "/books/magazines": {
      "get": {
        "summary": "公開 Books 掲載誌一覧",
        "operationId": "listBookMagazines",
        "responses": {
          "200": { "description": "掲載誌オブジェクトの配列", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BooksListResponse" } } } },
          "502": { "description": "Booksサービスの応答を取得できません" }
        }
      }
    },
    "/books/{bookId}": {
      "get": {
        "summary": "公開 Books 書籍詳細",
        "operationId": "getBook",
        "parameters": [
          { "name": "bookId", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$" } }
        ],
        "responses": {
          "200": { "description": "公開書籍オブジェクト", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BooksObject" } } } },
          "400": { "description": "書籍IDが不正です" },
          "502": { "description": "Booksサービスの応答を取得できません" }
        }
      }
    },
    "/books/series": {
      "get": {
        "summary": "公開 Books シリーズ一覧",
        "operationId": "listBookSeries",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 120 } }
        ],
        "responses": {
          "200": { "description": "公開シリーズオブジェクトの配列", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BooksListResponse" } } } },
          "502": { "description": "Booksサービスの応答を取得できません" }
        }
      }
    },
    "/books/series/{seriesId}": {
      "get": {
        "summary": "公開 Books シリーズ詳細",
        "operationId": "getBookSeries",
        "parameters": [
          { "name": "seriesId", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$" } }
        ],
        "responses": {
          "200": { "description": "公開シリーズ詳細オブジェクト", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BooksObject" } } } },
          "400": { "description": "シリーズIDが不正です" },
          "502": { "description": "Booksサービスの応答を取得できません" }
        }
      }
    },
    "/voice-actors": {
      "get": {
        "summary": "声優一覧",
        "operationId": "listVoiceActors",
        "parameters": [
          { "$ref": "#/components/parameters/Limit100" },
          { "$ref": "#/components/parameters/Offset" },
          { "$ref": "#/components/parameters/Search" },
          { "name": "ids", "in": "query", "schema": { "type": "string" }, "description": "数値 ID のカンマ区切り（最大50件）" }
        ],
        "responses": {
          "200": { "description": "声優一覧", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VoiceActorListResponse" } } } }
        }
      }
    },
    "/voice-actors/{id}": {
      "get": {
        "summary": "声優詳細",
        "description": "数字のみの値は常に声優IDとして扱います。数字以外の既存slugは後方互換のため引き続き利用できます。数字のみのslugは /voice-actors/by-slug/{slug} を使用してください。",
        "operationId": "getVoiceActor",
        "parameters": [
          { "$ref": "#/components/parameters/IdOrSlug" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500 }, "description": "出演情報の取得件数" },
          { "$ref": "#/components/parameters/Offset" }
        ],
        "responses": {
          "200": { "description": "プロフィールと出演情報", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VoiceActorDetail" } } } },
          "400": { "description": "limit または offset が不正です", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/voice-actors/by-slug/{slug}": {
      "get": {
        "summary": "声優詳細（slugを明示）",
        "description": "数字のみの既存slugを数値IDと区別して取得するための追加経路です。既存のID経路の意味は変更しません。",
        "operationId": "getVoiceActorBySlug",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500 }, "description": "出演情報の取得件数" },
          { "$ref": "#/components/parameters/Offset" }
        ],
        "responses": {
          "200": { "description": "プロフィールと出演情報", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VoiceActorDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/characters": {
      "get": {
        "summary": "キャラクター一覧",
        "operationId": "listCharacters",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 } },
          { "$ref": "#/components/parameters/Offset" },
          { "$ref": "#/components/parameters/Search" },
          { "name": "anime_id", "in": "query", "schema": { "type": "integer" } },
          { "name": "kana", "in": "query", "schema": { "type": "string" }, "description": "頭文字（ひらがな、または A-Z）" }
        ],
        "responses": {
          "200": { "description": "キャラクター一覧", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CharacterListResponse" } } } },
          "400": { "description": "anime_id が正の整数ではありません", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/characters/{id}": {
      "get": {
        "summary": "キャラクター詳細",
        "operationId": "getCharacter",
        "parameters": [{ "$ref": "#/components/parameters/NumericId" }],
        "responses": {
          "200": { "description": "キャラクター、作品、担当声優の情報", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CharacterDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/articles": {
      "get": {
        "summary": "記事一覧",
        "description": "公開記事と公開予定として表示される記事を返します。本文は記事詳細で取得します。",
        "operationId": "listArticles",
        "parameters": [
          { "$ref": "#/components/parameters/Limit100" },
          { "$ref": "#/components/parameters/Offset" },
          { "$ref": "#/components/parameters/Search" },
          { "name": "category", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "記事一覧", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ArticleListResponse" } } } }
        }
      }
    },
    "/articles/{id}": {
      "get": {
        "summary": "公開記事詳細",
        "operationId": "getArticle",
        "parameters": [{ "$ref": "#/components/parameters/NumericId" }],
        "responses": {
          "200": { "description": "公開済み記事の詳細", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ArticleDetail" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Limit100": { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } },
      "Offset": { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } },
      "Search": { "name": "search", "in": "query", "schema": { "type": "string" } },
      "NumericId": { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } },
      "IdOrSlug": { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "数値 ID または slug" },
      "SlugOrId": { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "slug または数値 ID" }
    },
    "responses": {
      "NotFound": {
        "description": "対象が存在しないか、公開されていません",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "NullableString": { "type": ["string", "null"] },
      "LocalizedText": {
        "type": "object",
        "required": ["ja", "en"],
        "properties": { "ja": { "type": ["string", "null"] }, "en": { "type": ["string", "null"] } }
      },
      "AnimeSummary": {
        "type": "object",
        "required": ["id", "title", "type", "status"],
        "properties": {
          "id": { "type": "integer" }, "slug": { "$ref": "#/components/schemas/NullableString" },
          "title": { "$ref": "#/components/schemas/LocalizedText" }, "type": { "type": "string" },
          "episodes": { "type": ["integer", "null"] }, "status": { "type": "string" },
          "season": { "$ref": "#/components/schemas/NullableString" }, "seasonYear": { "type": ["integer", "null"] },
          "imageUrl": { "$ref": "#/components/schemas/NullableString" }, "score": { "type": ["number", "null"] },
          "popularity": { "type": ["integer", "null"] }, "isAdult": { "type": "boolean" }
        }
      },
      "AnimeListResponse": {
        "type": "object", "required": ["data", "total", "hasMore"],
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/AnimeSummary" } },
          "total": { "type": "integer" }, "hasMore": { "type": "boolean" }
        }
      },
      "Cast": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" }, "characterName": { "type": "string" },
          "voiceActor": { "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "slug": { "$ref": "#/components/schemas/NullableString" } } }
        }
      },
      "AnimeDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/AnimeSummary" },
          {
            "type": "object",
            "properties": {
              "titleRomaji": { "$ref": "#/components/schemas/NullableString" },
              "titleKana": { "$ref": "#/components/schemas/NullableString" },
              "synopsis": { "$ref": "#/components/schemas/LocalizedText" },
              "airStartDate": { "$ref": "#/components/schemas/NullableString" },
              "airEndDate": { "$ref": "#/components/schemas/NullableString" },
              "coverUrl": { "$ref": "#/components/schemas/NullableString" },
              "updatedAt": { "type": "string", "format": "date-time" },
              "studio": { "type": ["object", "null"], "additionalProperties": true },
              "series": { "type": ["object", "null"], "additionalProperties": true },
              "seriesWorks": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "genres": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "streamingLinks": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "casts": { "type": "array", "items": { "$ref": "#/components/schemas/Cast" } }
            }
          }
        ]
      },
      "SeriesSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" }, "slug": { "type": "string" }, "title": { "$ref": "#/components/schemas/LocalizedText" },
          "imageUrl": { "$ref": "#/components/schemas/NullableString" }, "workCount": { "type": "integer" }
        }
      },
      "SeriesListResponse": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/SeriesSummary" } },
          "total": { "type": "integer" }, "hasMore": { "type": "boolean" }
        }
      },
      "SeriesDetail": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" }, "slug": { "type": "string" }, "title": { "$ref": "#/components/schemas/LocalizedText" },
          "titleKana": { "$ref": "#/components/schemas/NullableString" }, "synopsis": { "type": "object", "properties": { "ja": { "$ref": "#/components/schemas/NullableString" } } },
          "imageUrl": { "$ref": "#/components/schemas/NullableString" }, "coverUrl": { "$ref": "#/components/schemas/NullableString" },
          "updatedAt": { "type": "string", "format": "date-time" },
          "works": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "casts": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
        }
      },
      "VoiceActorSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" }, "slug": { "$ref": "#/components/schemas/NullableString" }, "name": { "type": "string" },
          "nameReading": { "$ref": "#/components/schemas/NullableString" }, "agency": { "$ref": "#/components/schemas/NullableString" },
          "birthday": { "$ref": "#/components/schemas/NullableString" }, "birthplace": { "$ref": "#/components/schemas/NullableString" },
          "photoUrl": { "$ref": "#/components/schemas/NullableString" }, "appearances": { "type": "integer" }
        }
      },
      "VoiceActorListResponse": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/VoiceActorSummary" } },
          "total": { "type": "integer" }, "hasMore": { "type": "boolean" }
        }
      },
      "VoiceActorDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/VoiceActorSummary" },
          {
            "type": "object",
            "properties": {
              "photoUrl": { "$ref": "#/components/schemas/NullableString" },
              "twitterUrl": { "$ref": "#/components/schemas/NullableString" }, "instagramUrl": { "$ref": "#/components/schemas/NullableString" },
              "youtubeUrl": { "$ref": "#/components/schemas/NullableString" }, "tiktokUrl": { "$ref": "#/components/schemas/NullableString" },
              "websiteUrl": { "$ref": "#/components/schemas/NullableString" }, "rolesTotal": { "type": "integer" },
              "rolesHasMore": { "type": "boolean" }, "years": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "roles": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
            }
          }
        ]
      },
      "CharacterSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" }, "characterName": { "type": "string" }, "imageUrl": { "$ref": "#/components/schemas/NullableString" },
          "anime": { "type": "object", "additionalProperties": true }, "voiceActor": { "type": "object", "additionalProperties": true }
        }
      },
      "CharacterListResponse": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/CharacterSummary" } },
          "total": { "type": "integer" }, "hasMore": { "type": "boolean" }
        }
      },
      "CharacterDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/CharacterSummary" },
          {
            "type": "object",
            "properties": {
              "updatedAt": { "type": "string", "format": "date-time" },
              "sameCast": { "type": "array", "items": { "$ref": "#/components/schemas/Cast" } },
              "otherRoles": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
            }
          }
        ]
      },
      "ArticleSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" }, "title": { "$ref": "#/components/schemas/LocalizedText" }, "excerpt": { "$ref": "#/components/schemas/LocalizedText" },
          "category": { "type": "string" }, "imageUrl": { "type": "string" }, "author": { "type": "string" },
          "publishedAt": { "type": ["string", "null"] }, "tags": { "type": "array", "items": { "type": "string" } },
          "status": { "type": "string" }, "comingSoon": { "type": "boolean" }
        }
      },
      "ArticleListResponse": {
        "type": "object",
        "required": ["data", "total", "hasMore"],
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/ArticleSummary" } },
          "total": { "type": "integer", "minimum": 0 },
          "hasMore": { "type": "boolean" }
        }
      },
      "ArticleDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/ArticleSummary" },
          {
            "type": "object",
            "properties": {
              "content": { "$ref": "#/components/schemas/LocalizedText" }, "contentBlocks": { "type": ["array", "null"], "items": { "type": "object", "additionalProperties": true } },
              "updatedAt": { "type": "string", "format": "date-time" }
            }
          }
        ]
      },
      "BooksObject": {
        "type": "object",
        "description": "Books upstream public object; additional fields are preserved for forward compatibility.",
        "additionalProperties": true,
        "properties": {
          "id": { "type": ["string", "integer"] },
          "bookId": { "type": "string" },
          "seriesId": { "type": "string" },
          "slug": { "type": "string" },
          "title": { "type": "string" },
          "name": { "type": "string" },
          "description": { "type": ["string", "null"] },
          "imageUrl": { "type": ["string", "null"], "format": "uri" },
          "coverUrl": { "type": ["string", "null"], "format": "uri" },
          "thumbnailUrl": { "type": ["string", "null"], "format": "uri" },
          "books": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } }
        }
      },
      "BooksListResponse": {
        "oneOf": [
          { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } },
          {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "books": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } },
              "series": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } },
              "magazines": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } },
              "items": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } },
              "data": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } },
              "results": { "type": "array", "items": { "$ref": "#/components/schemas/BooksObject" } }
            }
          }
        ]
      },
      "MangaTitleItem": {
        "type": "object",
        "description": "Manga upstream public object; additional fields are preserved until the upstream OpenAPI is published.",
        "additionalProperties": true,
        "properties": {
          "id": { "type": ["string", "integer"] },
          "titleId": { "type": ["string", "integer"] },
          "slug": { "type": "string" },
          "title": {},
          "name": {},
          "description": { "type": ["string", "null"] },
          "imageUrl": { "type": ["string", "null"], "format": "uri" },
          "coverUrl": { "type": ["string", "null"], "format": "uri" },
          "thumbnailUrl": { "type": ["string", "null"], "format": "uri" }
        }
      },
      "MangaHomeResponse": {
        "oneOf": [
          { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
          { "type": "object", "additionalProperties": true }
        ]
      },
      "MangaTitlesResponse": {
        "oneOf": [
          { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
          {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "titles": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
              "items": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
              "data": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
              "results": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } }
            }
          }
        ]
      },
      "MangaTitleDetailResponse": {
        "type": "object",
        "description": "Public Manga title detail with upstream chapter/access metadata.",
        "additionalProperties": true,
        "properties": {
          "id": { "type": ["string", "integer"] },
          "titleId": { "type": ["string", "integer"] },
          "slug": { "type": "string" },
          "title": {},
          "name": {},
          "description": { "type": ["string", "null"] },
          "chapters": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } }
        }
      },
      "MangaReaderResponse": {
        "oneOf": [
          { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
          {
            "type": "object",
            "description": "Public free-chapter reader envelope; exact page keys remain forward-compatible pending upstream OpenAPI.",
            "additionalProperties": true,
            "properties": {
              "pages": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
              "images": { "type": "array", "items": { "$ref": "#/components/schemas/MangaTitleItem" } },
              "pageUrls": { "type": "array", "items": { "type": "string", "format": "uri" } },
              "imageUrls": { "type": "array", "items": { "type": "string", "format": "uri" } }
            }
          }
        ]
      },
      "Error": { "type": "object", "properties": { "error": { "type": "string" } } }
    }
  }
}