{
 "openapi": "3.0.3",
 "info": {
  "title": "torishio工房 VRChat データ API",
  "version": "1.0.0",
  "description": "BOOTHで販売されているVRChat向けアバターのランキング・価格推移・対応アイテムと、\nVRChatワールドの一覧を返すAPIです。認証は不要で、そのまま呼び出せます。\n\n**このページから直接試せます。** 各エンドポイントの「Try it out」を押すと、\n実際のサーバーへリクエストを送って応答を確認できます。\n\n### 呼び出しにあたっての注意\n\n* **User-Agent を必ず指定してください。** Python の `urllib` が既定で送る\n  `Python-urllib/3.x` は 403 で拒否されます。`requests` や `curl` の既定値は通ります。\n* **レート制限は 10秒あたり40リクエスト**です。超えると30秒間 `429` を返し、\n  `Retry-After` ヘッダに待ち時間が入ります。連続取得は 0.3 秒ほど間隔を空けてください。\n* データは1日4回（0時・6時・12時・18時 JST）更新されます。\n\n### 価格の扱い（重要）\n\nBOOTHの商品ページには、アバター本体のほかに Quest版・無料の変換プロファイル・\n追加パーツなどが並ぶことがあります。BOOTHの一覧に出る「¥500〜」は\n**その中で最も安い構成**の価格で、本体の価格ではありません。\n\n本APIの `price` と `main_price_yen` には**アバター本体の価格**が入っています。\n最も安い構成が必要な場合は `min_variation_yen` を参照してください。\n\n`on_sale` / `is_on_sale` は「記録上の最高値より現在価格が低い」または\n「商品名にセールを示す語が含まれる」場合に立つ**参考値**で、\nBOOTHが公式に提供するセール情報ではありません。\n",
  "contact": {
   "name": "torishio工房（ブログ）",
   "url": "https://blog.hachune.space/"
  }
 },
 "servers": [
  {
   "url": "https://vrc.hachune.space/api/v1"
  }
 ],
 "tags": [
  {
   "name": "アバター",
   "description": "BOOTHのVRChat向けアバター"
  },
  {
   "name": "ワールド",
   "description": "VRChatのワールド"
  }
 ],
 "paths": {
  "/avatars": {
   "get": {
    "tags": [
     "アバター"
    ],
    "summary": "アバターの一覧を取得する",
    "description": "BOOTHの「3Dキャラクター」カテゴリをお気に入り数順に巡回した結果を返します。上位2400件を収録しています。1ページ100件です。",
    "operationId": "listAvatars",
    "parameters": [
     {
      "name": "mode",
      "in": "query",
      "description": "popular=人気順 / rising=人気急上昇 / new=新着 / bookmark=ID指定",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "popular",
        "rising",
        "new",
        "bookmark"
       ],
       "default": "popular"
      }
     },
     {
      "name": "page",
      "in": "query",
      "description": "ページ番号（1ページ100件）",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 1,
       "default": 1
      }
     },
     {
      "name": "sort",
      "in": "query",
      "description": "並び順",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "rank",
        "sale",
        "price",
        "price_desc",
        "name",
        "shop"
       ],
       "default": "rank"
      }
     },
     {
      "name": "q",
      "in": "query",
      "description": "アバター名・作者名の部分一致検索",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ids",
      "in": "query",
      "description": "mode=bookmark のときに使う商品IDのカンマ区切り。最大300件、指定した順に返ります",
      "required": false,
      "schema": {
       "type": "string"
      },
      "example": "6813995,6571299"
     }
    ],
    "responses": {
     "200": {
      "description": "成功",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/AvatarItem"
           }
          },
          "total": {
           "type": "integer",
           "description": "条件に一致した総件数"
          },
          "page": {
           "type": "integer",
           "description": "現在のページ番号"
          },
          "page_size": {
           "type": "integer",
           "description": "1ページあたりの件数"
          },
          "has_more": {
           "type": "boolean",
           "description": "次のページがあるか"
          }
         }
        }
       }
      }
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/TooManyRequests"
     }
    }
   }
  },
  "/avatar-detail": {
   "get": {
    "tags": [
     "アバター"
    ],
    "summary": "アバター1件の詳細を取得する",
    "description": "価格推移の全記録と、そのアバターに対応する衣装・髪型・小物を含みます。",
    "operationId": "getAvatarDetail",
    "parameters": [
     {
      "name": "item_id",
      "in": "query",
      "required": true,
      "description": "BOOTHの商品ID",
      "schema": {
       "type": "string"
      },
      "example": "6813995"
     }
    ],
    "responses": {
     "200": {
      "description": "成功",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "item": {
           "type": "object",
           "properties": {
            "item_id": {
             "type": "string",
             "description": "BOOTHの商品ID"
            },
            "name": {
             "type": "string",
             "description": "商品名"
            },
            "shop_name": {
             "type": "string",
             "description": "作者名"
            },
            "shop_url": {
             "type": "string",
             "description": "ショップURL"
            },
            "item_url": {
             "type": "string",
             "description": "商品ページURL"
            },
            "image_url": {
             "type": "string",
             "description": "サムネイルURL"
            },
            "price": {
             "type": "string",
             "description": "表示用の価格文字列（本体価格）"
            },
            "rank_position": {
             "type": "integer",
             "description": "順位"
            },
            "main_price_yen": {
             "type": "integer",
             "description": "アバター本体の価格",
             "nullable": true
            },
            "min_variation_yen": {
             "type": "integer",
             "description": "同じ商品ページで最も安い構成の価格",
             "nullable": true
            },
            "variation_count": {
             "type": "integer",
             "description": "構成の数。2以上なら複数構成の商品"
            }
           }
          },
          "compatible": {
           "type": "object",
           "description": "対応アイテム。「衣装」「髪型」「小物」「装飾品」をキーにした配列",
           "additionalProperties": {
            "type": "array",
            "items": {
             "$ref": "#/components/schemas/CompatibleItem"
            }
           }
          },
          "history": {
           "type": "array",
           "description": "価格推移（日付の昇順）",
           "items": {
            "$ref": "#/components/schemas/PriceHistoryPoint"
           }
          },
          "min_price": {
           "type": "integer",
           "description": "記録期間内の最安値",
           "nullable": true
          },
          "max_price": {
           "type": "integer",
           "description": "記録期間内の最高値",
           "nullable": true
          },
          "current_price": {
           "type": "integer",
           "description": "最新の記録価格",
           "nullable": true
          },
          "is_on_sale": {
           "type": "boolean",
           "description": "最新価格が記録上の最高値を下回っていれば true（参考値）"
          },
          "days_tracked": {
           "type": "integer",
           "description": "価格を記録した日数"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "item_id が指定されていません",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "指定した商品が見つかりません",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TooManyRequests"
     }
    }
   }
  },
  "/worlds": {
   "get": {
    "tags": [
     "ワールド"
    ],
    "summary": "VRChatワールドの一覧を取得する",
    "description": "**応答はオブジェクトではなく配列です**（アバターのAPIと形が違います）。最大200件返ります。",
    "operationId": "listWorlds",
    "parameters": [
     {
      "name": "season",
      "in": "query",
      "description": "分類で絞り込む",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "all",
        "beginner",
        "spring",
        "summer",
        "autumn",
        "winter",
        "chill",
        "vsleep",
        "jp_community",
        "popular"
       ],
       "default": "all"
      }
     },
     {
      "name": "mode",
      "in": "query",
      "description": "rising=お気に入りの伸び順 / new=公開1週間以内 / bookmark=ID指定",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "rising",
        "new",
        "bookmark"
       ]
      }
     },
     {
      "name": "sort",
      "in": "query",
      "description": "並び順",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "favorites",
        "name",
        "author",
        "newest",
        "curator"
       ],
       "default": "favorites"
      }
     },
     {
      "name": "q",
      "in": "query",
      "description": "ワールド名・作者名の部分一致検索",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ids",
      "in": "query",
      "description": "mode=bookmark のときのワールドIDのカンマ区切り。最大300件、指定した順に返ります",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "成功",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/World"
         }
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TooManyRequests"
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "AvatarItem": {
    "type": "object",
    "properties": {
     "item_id": {
      "type": "string",
      "description": "BOOTHの商品ID",
      "example": "6813995"
     },
     "name": {
      "type": "string",
      "description": "商品名"
     },
     "shop_name": {
      "type": "string",
      "description": "作者（ショップ）名"
     },
     "shop_url": {
      "type": "string",
      "description": "ショップのURL"
     },
     "item_url": {
      "type": "string",
      "description": "BOOTHの商品ページURL"
     },
     "image_url": {
      "type": "string",
      "description": "サムネイル画像のURL"
     },
     "price": {
      "type": "string",
      "description": "表示用の価格文字列。アバター本体の価格",
      "example": "¥ 6,000"
     },
     "rank_position": {
      "type": "integer",
      "description": "お気に入り数順の順位。順位が付いていない場合は 0"
     },
     "new_arrival_rank": {
      "type": "integer",
      "description": "新着順の順位。新着でなければ null",
      "nullable": true
     },
     "manual_added": {
      "type": "integer",
      "description": "BOOTHの一覧に出ないため手動で登録した商品なら 1"
     },
     "on_sale": {
      "type": "integer",
      "description": "セールの可能性があれば 1（参考値）"
     },
     "discount": {
      "type": "integer",
      "description": "記録上の最高値からの値下げ率(%)"
     },
     "rise": {
      "type": "integer",
      "description": "記録開始時からの順位上昇幅"
     }
    }
   },
   "CompatibleItem": {
    "type": "object",
    "properties": {
     "category": {
      "type": "string",
      "description": "衣装 / 髪型 / 小物 / 装飾品"
     },
     "item_id": {
      "type": "string",
      "description": "BOOTHの商品ID"
     },
     "name": {
      "type": "string",
      "description": "商品名"
     },
     "shop_name": {
      "type": "string",
      "description": "作者名"
     },
     "item_url": {
      "type": "string",
      "description": "商品ページURL"
     },
     "image_url": {
      "type": "string",
      "description": "サムネイルURL"
     },
     "price": {
      "type": "string",
      "description": "表示用の価格文字列"
     }
    }
   },
   "World": {
    "type": "object",
    "properties": {
     "world_id": {
      "type": "string",
      "description": "VRChatのワールドID",
      "example": "wrld_57514404-7f4e-4aee-a50a-57f55d3084bf"
     },
     "name": {
      "type": "string",
      "description": "ワールド名"
     },
     "author_name": {
      "type": "string",
      "description": "作者名"
     },
     "image_url": {
      "type": "string",
      "description": "サムネイルURL"
     },
     "world_url": {
      "type": "string",
      "description": "VRChat上のワールドページURL"
     },
     "favorites": {
      "type": "integer",
      "description": "お気に入り数"
     },
     "heat": {
      "type": "integer",
      "description": "VRChatのheat値"
     },
     "capacity": {
      "type": "integer",
      "description": "定員"
     },
     "season": {
      "type": "string",
      "description": "分類タグ",
      "nullable": true
     },
     "curator_score": {
      "type": "integer",
      "description": "掲載時の評価値",
      "nullable": true
     },
     "publication_date": {
      "type": "string",
      "description": "公開日",
      "nullable": true
     },
     "rise": {
      "type": "integer",
      "description": "記録開始時からのお気に入り増加数"
     }
    }
   },
   "PriceHistoryPoint": {
    "type": "object",
    "properties": {
     "recorded_date": {
      "type": "string",
      "description": "記録日 (YYYY-MM-DD)",
      "example": "2026-08-28"
     },
     "price_yen": {
      "type": "string",
      "description": "その日の価格（円）。文字列で返ります",
      "example": "6000"
     }
    }
   },
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "string",
      "description": "エラーの内容"
     }
    }
   }
  },
  "responses": {
   "TooManyRequests": {
    "description": "レート制限。10秒あたり40リクエストを超えました。Retry-After ヘッダの秒数だけ待ってから再試行してください。",
    "headers": {
     "Retry-After": {
      "schema": {
       "type": "integer"
      },
      "description": "待機すべき秒数"
     }
    }
   },
   "Forbidden": {
    "description": "User-Agent が拒否対象です。Python-urllib の既定値ではなく、アプリ名を名乗るUAを指定してください。"
   }
  }
 }
}