openapi: 3.1.0
info:
  title: benriscore API
  version: 0.2.0
  description: |-
    日本国内の任意の緯度経度に対して、全国で正規化された便利度スコアを返す API です。 LLM エージェントによる引用を前提に `cite_as` / `purpose_context` field を提供しています。

    全てのエラーレスポンスは `{ error: { code, message } }` の共通 shape を持ちます。 `code` は安定した識別子、 `message` は状況の説明文です。

    data attribution: 成功レスポンスには `X-Benriscore-Attribution` / `X-Benriscore-Tile-Version` header と body 内の `attribution` field が含まれます。 利用条件は [利用規約](https://benriscore.com/docs/api/terms) を参照。
  termsOfService: https://benriscore.com/docs/api/terms
  license:
    name: 利用規約
    url: https://benriscore.com/docs/api/terms
  contact:
    name: benriscore
    url: https://benriscore.com
servers:
  - url: https://api.benriscore.com
tags:
  - name: point
    description: 座標 1 点の便利度スコア。
  - name: search
    description: 都道府県 / 市区町村 / 町丁目 を横断した名前検索。
  - name: extremes
    description: metric 上位 / 下位 N 件 ranking。
  - name: compare
    description: 2 entity の直接比較。
  - name: summary
    description: 1 area の概観 (主要 metric / top 3 / bottom 3)。
  - name: nearest
    description: 座標から近傍 N 件。
  - name: query-areas
    description: filter + sort で area を検索。
  - name: neighbors
    description: 行政区画の隣接 polygon。
  - name: ask
    description: 自然言語クエリで area / entity を検索。
  - name: keys
    description: API キー発行。
  - name: inquiry
    description: B2B 法人プラン お問い合わせ。
  - name: tiles
    description: ベクタータイル配信。
  - name: tiles-archive
    description: ベクタータイル配信 (過去バージョン archive)。
  - name: mcp
    description: Model Context Protocol (JSON-RPC 2.0)。
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: bk_live_<24-char-base64url>
      description: |-
        `/v1/keys/issue` で発行した API キーによる Bearer 認証。
        `Authorization: Bearer bk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` の形式で送信してください。
  headers:
    XBenriscoreAttribution:
      schema:
        type: string
        example: OpenStreetMap contributors (ODbL 1.0)
      description: ODbL の attribution 文字列。利用側アプリケーションで表示・保持することが必須です。
    XBenriscoreTileVersion:
      schema:
        type: string
        format: date
        example: 2026-04-18
      description: タイルのビルド日付。クライアント側のキャッシュ無効化判定に利用できます。
    XBenriscoreSearchVersion:
      schema:
        type: string
        example: 2026-04-18
      description: 検索インデックスのビルド日付。
    XBenriscoreSearchSources:
      schema:
        type: string
        example: OpenStreetMap contributors (ODbL 1.0)
      description: 検索結果に含まれる data source の attribution 文字列です。 複数 source が混在する場合は `;` で区切って連結されます。
    RetryAfter:
      schema:
        type: integer
        example: 42
      description: 再試行までに待つべき秒数。`429` レスポンス時に付与されます。
  responses:
    InvalidParams:
      description: リクエストパラメータに問題がある場合のレスポンスです。 例として 必須パラメータの欠落、 範囲外、 未知の enum 値、 利用規約への未同意、 ボットチェック失敗などで返されます。
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            invalid_params:
              value:
                error:
                  code: invalid_params
                  message: lat and lon query parameters are required
    Unauthorized:
      description: Authorization header が存在しない、 形式が不正、 またはキーが見つからない / 無効化されている場合のレスポンスです。
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            unauthorized:
              summary: Bearer header が欠落または形式不正
              value:
                error:
                  code: unauthorized
                  message: "Missing or malformed Authorization header (expected: Bearer <api_key>)"
            invalid_key:
              summary: キーの形式は正しいが、登録済みキーに一致しない / 無効化済み
              value:
                error:
                  code: invalid_key
                  message: Invalid or revoked API key
    NotFound:
      description: 対象の resource が存在しない場合のレスポンスです (日本国外の座標、 未知の area code、 駅名など)。
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            not_found:
              value:
                error:
                  code: not_found
                  message: Coordinate is outside Japan; benriscore covers Japan only
    RateLimited:
      description: レート制限を超過した場合のレスポンス。`Retry-After` header の秒数だけ待って再試行してください。
      headers:
        Retry-After:
          $ref: "#/components/headers/RetryAfter"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            rate_limited:
              value:
                error:
                  code: rate_limited
                  message: Rate limit exceeded
    InternalError:
      description: 想定外のサーバーエラーが発生した場合のレスポンスです。
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            internal_error:
              value:
                error:
                  code: internal_error
                  message: Internal server error
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - unauthorized
                - invalid_key
                - invalid_params
                - rate_limited
                - not_found
                - forbidden
                - internal_error
            message:
              type: string
          required:
            - code
            - message
      required:
        - error
      description: 全エラーレスポンスの共通 shape です。
    ExtremeMetric:
      type: string
      enum:
        - total
      description: ranking / 比較 / filter に使う metric です。 ADR-029 X3d 以降は `total` のみ受理されます。 旧 26 subcategory slug は撤去済です。
    SearchScope:
      type: string
      enum:
        - pref
        - muni
        - chochome
    CiteAs:
      type: object
      properties:
        short:
          type: string
          example: benriscore 88/100
        sentence_ja:
          type: string
          example: "benriscore の便利度スコアは 88/100 です (鉄道駅: 100、バス停: 100)。"
        sentence_en:
          type: string
          example: "benriscore rates this location 88/100 (rail stations: 100, bus stops: 100)."
        url:
          type: string
          format: uri
          example: https://benriscore.com/point?lat=35.681200&lon=139.767100
      required:
        - short
        - sentence_ja
        - sentence_en
        - url
      description: LLM による引用を前提に設計された citation 文字列です。
    PurposeContext:
      type: object
      properties:
        cohort:
          type: string
          enum:
            - general
          example: general
        cohort_available:
          type: array
          items:
            type: string
          example:
            - general
        cohort_roadmap:
          type: array
          items:
            type: string
            enum:
              - family
              - single
              - senior
          example:
            - family
            - single
            - senior
        weighting_rationale_ja:
          type: string
        weighting_rationale_en:
          type: string
      required:
        - cohort
        - cohort_available
        - cohort_roadmap
        - weighting_rationale_ja
        - weighting_rationale_en
      description: 目的別 (purpose-aware) の positioning 用 scaffold です。 利用可能な cohort 集合は `cohort_available` を参照してください。
    SearchResultEntity:
      type: object
      properties:
        scope:
          type: string
          enum:
            - pref
            - muni
            - chochome
            - station
        code:
          type: string
        name:
          type: string
        parent_path:
          type: string
        lng:
          type: number
        lat:
          type: number
        zoom:
          type: integer
        source:
          type: string
          enum:
            - estat
            - osm
            - mlit
        score:
          type:
            - number
            - "null"
          minimum: 0
          maximum: 100
        cite_as:
          $ref: "#/components/schemas/CiteAs"
        purpose_context:
          $ref: "#/components/schemas/PurposeContext"
      required:
        - scope
        - code
        - name
        - parent_path
        - lng
        - lat
        - zoom
        - source
        - score
        - cite_as
        - purpose_context
      description: search / extremes / nearest / compare / query-areas / neighbors の結果 row 共通 shape です。
    SimpleAnchor:
      type: object
      properties:
        scope:
          type: string
          enum:
            - pref
            - muni
            - chochome
            - station
        code:
          type: string
        name:
          type: string
      required:
        - scope
        - code
        - name
      description: neighbors の anchor など、 軽量な entity 参照に使う shape です。
    Point:
      type: object
      properties:
        lat:
          type: number
          example: 35.6812
        lon:
          type: number
          example: 139.7671
      required:
        - lat
        - lon
    Meta:
      type: object
      properties:
        tile_version:
          type: string
          example: 2026-04-18
        source_zoom:
          type: integer
          minimum: 9
          maximum: 15
          example: 15
        computed_at:
          type: string
          example: 2026-04-22T10:00:00.000Z
      required:
        - tile_version
        - source_zoom
        - computed_at
    PointResponse:
      type: object
      properties:
        point:
          $ref: "#/components/schemas/Point"
        attribution:
          type: string
          example: OpenStreetMap contributors (ODbL 1.0)
        meta:
          $ref: "#/components/schemas/Meta"
        cite_as:
          $ref: "#/components/schemas/CiteAs"
        purpose_context:
          $ref: "#/components/schemas/PurposeContext"
      required:
        - point
        - attribution
        - meta
        - cite_as
        - purpose_context
      description: client は未知の top-level field に備えて防御的アクセス (optional chaining 等) を推奨します。
    SearchResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: "#/components/schemas/SearchResultEntity"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            used_fallback:
              type: boolean
          required:
            - search_index_version
            - intent_classified
            - used_fallback
      required:
        - results
        - meta
    ExtremeAnchor:
      oneOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - global
          required:
            - type
        - type: object
          properties:
            type:
              type: string
              enum:
                - station
            code:
              type: string
            name:
              type: string
            lat:
              type: number
            lon:
              type: number
            radius_m:
              type: number
          required:
            - type
            - code
            - name
        - type: object
          properties:
            type:
              type: string
              enum:
                - pref
            code:
              type: string
            name:
              type: string
          required:
            - type
            - code
            - name
        - type: object
          properties:
            type:
              type: string
              enum:
                - muni
            code:
              type: string
            name:
              type: string
          required:
            - type
            - code
            - name
    ExtremesResponse:
      type: object
      properties:
        anchor:
          $ref: "#/components/schemas/ExtremeAnchor"
        results:
          type: array
          items:
            $ref: "#/components/schemas/SearchResultEntity"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            scope:
              type: string
              enum:
                - chochome
            metric:
              $ref: "#/components/schemas/ExtremeMetric"
            dir:
              type: string
              enum:
                - min
                - max
            within: {}
          required:
            - search_index_version
            - intent_classified
            - scope
            - metric
            - dir
      required:
        - anchor
        - results
        - meta
    CompareDiff:
      type: object
      properties:
        metric:
          $ref: "#/components/schemas/ExtremeMetric"
        a_score:
          type:
            - number
            - "null"
        b_score:
          type:
            - number
            - "null"
        delta:
          type:
            - number
            - "null"
      required:
        - metric
        - a_score
        - b_score
        - delta
    CompareResponse:
      type: object
      properties:
        a:
          $ref: "#/components/schemas/SearchResultEntity"
        b:
          $ref: "#/components/schemas/SearchResultEntity"
        diffs:
          type: array
          items:
            $ref: "#/components/schemas/CompareDiff"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            metrics:
              type: array
              items:
                type: string
          required:
            - search_index_version
            - intent_classified
            - metrics
      required:
        - a
        - b
        - diffs
        - meta
    SummaryMetricEntry:
      type: object
      properties:
        metric:
          $ref: "#/components/schemas/ExtremeMetric"
        score:
          type:
            - number
            - "null"
      required:
        - metric
        - score
    SummaryResponse:
      type: object
      properties:
        entity:
          $ref: "#/components/schemas/SearchResultEntity"
        all_metrics:
          type: array
          items:
            $ref: "#/components/schemas/SummaryMetricEntry"
        top_3:
          type: array
          items:
            $ref: "#/components/schemas/SummaryMetricEntry"
        bottom_3:
          type: array
          items:
            $ref: "#/components/schemas/SummaryMetricEntry"
        nearby:
          type: array
          items:
            $ref: "#/components/schemas/SearchResultEntity"
          description: "`include_neighbors=true` を指定した場合のみ含まれます。"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            scope:
              type: string
              enum:
                - chochome
            code:
              type: string
            include_neighbors:
              type: boolean
          required:
            - search_index_version
            - intent_classified
            - scope
            - code
            - include_neighbors
      required:
        - entity
        - all_metrics
        - top_3
        - bottom_3
        - meta
    NearestResultEntity:
      allOf:
        - $ref: "#/components/schemas/SearchResultEntity"
        - type: object
          properties:
            distance_m:
              type: number
              description: anchor 座標からの距離 (メートル) です。
              example: 32.7
          required:
            - distance_m
      description: search / extremes / nearest / compare / query-areas / neighbors の結果 row 共通 shape です。
    NearestResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: "#/components/schemas/NearestResultEntity"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            scope:
              type: string
              enum:
                - chochome
            lng:
              type: number
            lat:
              type: number
            filter:
              type:
                - object
                - "null"
              properties:
                metric:
                  $ref: "#/components/schemas/ExtremeMetric"
                threshold:
                  type: number
              required:
                - metric
                - threshold
          required:
            - search_index_version
            - intent_classified
            - scope
            - lng
            - lat
            - filter
      required:
        - results
        - meta
    MetricThreshold:
      type: object
      properties:
        metric:
          $ref: "#/components/schemas/ExtremeMetric"
        threshold:
          type: number
      required:
        - metric
        - threshold
    QueryAreasFilter:
      type: object
      properties:
        parent_pref_query:
          type: string
        parent_muni_query:
          type: string
        near_station_query:
          type: string
        near_station_buffer_m:
          type: number
        exclude_pref_queries:
          type: array
          items:
            type: string
        metric_min:
          type: array
          items:
            $ref: "#/components/schemas/MetricThreshold"
        metric_max:
          type: array
          items:
            $ref: "#/components/schemas/MetricThreshold"
    QueryAreasSort:
      type: object
      properties:
        metric:
          $ref: "#/components/schemas/ExtremeMetric"
        dir:
          type: string
          enum:
            - min
            - max
      required:
        - metric
        - dir
    QueryAreasRequest:
      type: object
      properties:
        scope:
          type: string
          enum:
            - chochome
        filter:
          $ref: "#/components/schemas/QueryAreasFilter"
        sort:
          $ref: "#/components/schemas/QueryAreasSort"
        limit:
          type: integer
          minimum: 1
          maximum: 50
      required:
        - scope
    QueryAreasResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: "#/components/schemas/SearchResultEntity"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            scope:
              type: string
              enum:
                - chochome
            filter:
              allOf:
                - $ref: "#/components/schemas/QueryAreasFilter"
                - type:
                    - object
                    - "null"
            sort:
              allOf:
                - $ref: "#/components/schemas/QueryAreasSort"
                - type:
                    - object
                    - "null"
            limit:
              type:
                - integer
                - "null"
          required:
            - search_index_version
            - intent_classified
            - scope
            - filter
            - sort
            - limit
      required:
        - results
        - meta
    NeighborsResponse:
      type: object
      properties:
        anchor:
          $ref: "#/components/schemas/SimpleAnchor"
        neighbors:
          type: array
          items:
            $ref: "#/components/schemas/SearchResultEntity"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
              enum:
                - false
            scope:
              type: string
              enum:
                - pref
                - muni
            code:
              type: string
          required:
            - search_index_version
            - intent_classified
            - scope
            - code
      required:
        - anchor
        - neighbors
        - meta
    AskRequest:
      type: object
      properties:
        q:
          type: string
          minLength: 1
          maxLength: 500
          description: 自然言語の質問。 サーバー側で意図を解析し、 search / extremes / compare / summary / nearest / query-areas のいずれかの処理に振り分けて結果を返します。
          example: 新宿駅から徒歩 10 分以内で病院アクセスが良いエリアは?
      required:
        - q
    AskResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: "#/components/schemas/SearchResultEntity"
        meta:
          type: object
          properties:
            search_index_version:
              type:
                - string
                - "null"
            intent_classified:
              type: boolean
            used_fallback:
              type: boolean
            tool_used:
              type: string
              enum:
                - search_entity
                - find_extreme
                - compare_areas
                - summarize_area
                - find_nearest
                - query_areas
            tool_input:
              type: object
              additionalProperties: {}
          required:
            - search_index_version
            - intent_classified
      required:
        - results
        - meta
      description: サーバーが選択した処理 (`tool_used`) に応じて追加 top-level field (anchor / a / b / diffs など) が含まれることがあります。 client は防御的アクセスを推奨します。
    McpRequest:
      type: object
      properties:
        jsonrpc:
          type: string
          enum:
            - "2.0"
        id:
          anyOf:
            - type: string
            - type: number
        method:
          type: string
          description: "MCP method 名を指定します (例: initialize / tools/list / tools/call / ping / notifications/initialized)。"
        params:
          type: object
          additionalProperties: {}
      required:
        - jsonrpc
        - method
      description: JSON-RPC 2.0 形式のリクエストです。 `notifications/*` の method は id を持たず、 レスポンスを返しません。
    McpResponse:
      type: object
      properties:
        jsonrpc:
          type: string
          enum:
            - "2.0"
        id:
          anyOf:
            - type: string
            - type: number
            - type: "null"
        result: {}
        error:
          type: object
          properties:
            code:
              type: integer
            message:
              type: string
            data: {}
          required:
            - code
            - message
      required:
        - jsonrpc
        - id
      description: JSON-RPC 2.0 形式のレスポンスです。 `result` または `error` のいずれかを含みます。
  parameters: {}
paths:
  /v1/point:
    get:
      tags:
        - point
      summary: 座標の便利度メタを取得
      description: 日本国内の単一座標に対する benriscore の cite_as / purpose_context メタを返します。 旧 score (= 26 subcategory) field は ADR-029 X3d (2026-05-07) で撤去済、 cohort 軸の score は後続 PR で再設計予定。
      operationId: getPoint
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: number
            minimum: 20
            maximum: 46
            description: 緯度 (日本国内) を指定します。
            example: 35.6812
          required: true
          description: 緯度 (日本国内) を指定します。
          name: lat
          in: query
        - schema:
            type: number
            minimum: 122
            maximum: 154
            description: 経度 (日本国内) を指定します。
            example: 139.7671
          required: true
          description: 経度 (日本国内) を指定します。
          name: lon
          in: query
        - schema:
            type: integer
            minimum: 9
            maximum: 15
            description: ベクタータイルの source zoom を指定します。 default は 15 です。
            example: 15
          required: false
          description: ベクタータイルの source zoom を指定します。 default は 15 です。
          name: zoom
          in: query
        - schema:
            type: string
            description: 返却する内容を指定します (複数指定時は カンマまたは空白区切り)。 ADR-029 X3d 以降は default 空 (= 利用可能な resolver は将来追加予定)。
          required: false
          description: 返却する内容を指定します (複数指定時は カンマまたは空白区切り)。 ADR-029 X3d 以降は default 空 (= 利用可能な resolver は将来追加予定)。
          name: include
          in: query
        - schema:
            type: string
            enum:
              - general
            description: 目的別 (cohort) の重み付けを指定します。
          required: false
          description: 目的別 (cohort) の重み付けを指定します。
          name: cohort
          in: query
      responses:
        "200":
          description: 指定座標のスコア計算に成功した場合のレスポンスです。
          headers:
            X-Benriscore-Attribution:
              $ref: "#/components/headers/XBenriscoreAttribution"
            X-Benriscore-Tile-Version:
              $ref: "#/components/headers/XBenriscoreTileVersion"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PointResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/search:
    get:
      tags:
        - search
      summary: 都道府県 / 市区町村 / 町丁目 を横断して名前検索
      description: 都道府県 / 市区町村 / 町丁目 を横断して entity を検索します。 全文検索 + 部分一致 fallback で名寄せします。 query 末尾の `駅` は サーバー側で正規化されるため `新宿駅` でもヒットします。
      operationId: searchEntities
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            description: 検索文字列を指定します。
            example: 新宿
          required: true
          description: 検索文字列を指定します。
          name: q
          in: query
        - schema:
            type: string
            enum:
              - pref
              - muni
              - chochome
            description: scope を絞り込む場合に指定します。
          required: false
          description: scope を絞り込む場合に指定します。
          name: scope
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
            description: 返却件数の上限を指定します。 default は 10 です。
          required: false
          description: 返却件数の上限を指定します。 default は 10 です。
          name: limit
          in: query
      responses:
        "200":
          description: 検索結果です。 0 件の場合は results が空配列で返ります。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SearchResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/extremes:
    get:
      tags:
        - extremes
      summary: score 上位 / 下位 N 件 (任意 anchor 内 ranking)
      description: 町丁目単位で `total` score の上位 / 下位 N 件を返します。 anchor (`within_type` + `within_query`) で 駅徒歩圏 / 都道府県内 / 市区町村内 に絞り込めます。 anchor 省略時は全国 ranking として動作します。 旧 API の `?station=` 引数は `within_type=station_buffer` の alias として受理します。 ADR-029 X3d (2026-05-07) で metric は `total` のみ受理 (旧 26 subcategory slug は撤去済)。
      operationId: findExtremes
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            enum:
              - chochome
            description: default は 'chochome' です。
          required: false
          description: default は 'chochome' です。
          name: scope
          in: query
        - schema:
            allOf:
              - $ref: "#/components/schemas/ExtremeMetric"
              - description: ranking 対象の metric を指定します。 ADR-029 X3d 以降は `total` のみ受理。
          required: true
          description: ranking 対象の metric を指定します。 ADR-029 X3d 以降は `total` のみ受理。
          name: metric
          in: query
        - schema:
            type: string
            enum:
              - min
              - max
            description: 上位 (max) / 下位 (min) を指定します。
          required: true
          description: 上位 (max) / 下位 (min) を指定します。
          name: dir
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
            enum:
              - station_buffer
              - pref
              - muni
            description: anchor の種別を指定します。
          required: false
          description: anchor の種別を指定します。
          name: within_type
          in: query
        - schema:
            type: string
            description: anchor の検索文字列 (駅名 / 都道府県名 / 市区町村名) を指定します。
          required: false
          description: anchor の検索文字列 (駅名 / 都道府県名 / 市区町村名) を指定します。
          name: within_query
          in: query
        - schema:
            type:
              - number
              - "null"
            description: station_buffer 指定時のみ有効です。 default は徒歩 10 分相当の値となります。
          required: false
          description: station_buffer 指定時のみ有効です。 default は徒歩 10 分相当の値となります。
          name: radius_m
          in: query
        - schema:
            type: string
            description: 旧 API alias です。 `within_type=station_buffer` + `within_query=<station>` と等価で、 互換のため受理されますが、 新規実装では `within_type` を使ってください。
            deprecated: true
          required: false
          description: 旧 API alias です。 `within_type=station_buffer` + `within_query=<station>` と等価で、 互換のため受理されますが、 新規実装では `within_type` を使ってください。
          name: station
          in: query
      responses:
        "200":
          description: ranking 結果です。 anchor の解決情報も meta に含まれます。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ExtremesResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/compare:
    get:
      tags:
        - compare
      summary: 2 area 直接比較
      description: 2 entity を直接比較します。
      operationId: compareAreas
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            enum:
              - chochome
          required: true
          name: a_scope
          in: query
        - schema:
            type: string
            minLength: 1
          required: true
          name: a_code
          in: query
        - schema:
            type: string
            enum:
              - chochome
          required: true
          name: b_scope
          in: query
        - schema:
            type: string
            minLength: 1
          required: true
          name: b_code
          in: query
        - schema:
            type: string
            description: "comma-separated 列 (例: 'total')。 ADR-029 X3d (2026-05-07) で 旧 26 subcategory slug は撤去済、 'total' のみ valid。"
          required: false
          description: "comma-separated 列 (例: 'total')。 ADR-029 X3d (2026-05-07) で 旧 26 subcategory slug は撤去済、 'total' のみ valid。"
          name: metrics
          in: query
      responses:
        "200":
          description: 2 entity の比較結果です。 diffs 配列に metric 別の差分が並びます。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CompareResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/summary:
    get:
      tags:
        - summary
      summary: 1 area の概観要約
      description: 1 area (scope + code) の `total` metric / (任意で近隣 entity) を返します。 ADR-029 X3d (2026-05-07) で 旧 26 subcategory metric は撤去済、 `all_metrics` / `top_3` / `bottom_3` は `total` 1 件のみ含みます。
      operationId: summarizeArea
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            enum:
              - chochome
          required: true
          name: scope
          in: query
        - schema:
            type: string
            minLength: 1
          required: true
          name: code
          in: query
        - schema:
            type: string
            enum:
              - "0"
              - "1"
              - "true"
              - "false"
              - yes
              - no
            description: "`true` / `1` / `yes` を指定すると nearby が返却されます。"
          required: false
          description: "`true` / `1` / `yes` を指定すると nearby が返却されます。"
          name: include_neighbors
          in: query
      responses:
        "200":
          description: area の概観です。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SummaryResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/nearest:
    get:
      tags:
        - nearest
      summary: 座標から近傍 N 件 (任意 metric_min フィルタ付)
      description: lng/lat を anchor として、 scope の近傍 entity を距離昇順で返します。 `metric_min_metric` + `metric_min_threshold` を両方指定すると、 `total` score が threshold 以上の entity だけに絞り込めます。 ADR-029 X3d (2026-05-07) で metric は `total` のみ受理 (旧 26 subcategory slug は撤去済)。
      operationId: findNearest
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: number
            minimum: 122
            maximum: 154
          required: true
          name: lng
          in: query
        - schema:
            type: number
            minimum: 20
            maximum: 46
          required: true
          name: lat
          in: query
        - schema:
            type: string
            enum:
              - chochome
          required: true
          name: scope
          in: query
        - schema:
            $ref: "#/components/schemas/ExtremeMetric"
          required: false
          description: ranking / 比較 / filter に使う metric です。 ADR-029 X3d 以降は `total` のみ受理されます。 旧 26 subcategory slug は撤去済です。
          name: metric_min_metric
          in: query
        - schema:
            type:
              - number
              - "null"
          required: false
          name: metric_min_threshold
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: 近傍 entity の距離昇順リストです。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NearestResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/query-areas:
    post:
      tags:
        - query-areas
      summary: 条件指定 area 検索 (filter + sort)
      description: filter (親 pref / muni / 駅徒歩圏 / metric_min / metric_max など) と sort (metric + dir) を組合せて scope 内の entity を検索します。 nested な filter を受けるため POST にしています。 ADR-029 X3d (2026-05-07) で metric は `total` のみ受理 (旧 26 subcategory slug は撤去済)。
      operationId: queryAreas
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/QueryAreasRequest"
      responses:
        "200":
          description: filter + sort の結果です。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/QueryAreasResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/neighbors:
    get:
      tags:
        - neighbors
      summary: 行政区画の隣接 polygon graph
      description: scope (pref / muni) + code で指定した行政区画に **隣接** する polygon を返します。
      operationId: findNeighbors
      security:
        - BearerAuth: []
      parameters:
        - schema:
            type: string
            enum:
              - pref
              - muni
          required: true
          name: scope
          in: query
        - schema:
            type: string
            minLength: 1
          required: true
          name: code
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 50
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: anchor と隣接 entity リストを返します。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NeighborsResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /v1/ask:
    post:
      tags:
        - ask
      summary: 自然言語クエリで area / entity を検索
      description: |-
        自然言語の質問を サーバー側で意図解析し、 適切な処理に振り分けて結果を返します。 解析できなかった場合は通常の検索結果に fallback し、 必ず 200 を返します。

        rate limit は `/v1/ask` 専用枠 (10 req/min, 200 req/day per key) で、 他 endpoint (30/min, 1000/day) とは独立です。

        プライバシー: 送信した query 文字列はサーバー側のログ / 永続ストレージに書き込みません。
      operationId: askNl
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AskRequest"
      responses:
        "200":
          description: 意図解析に成功した場合は対応する処理の結果が、 失敗した場合は通常の検索結果が返されます。
          headers:
            X-Benriscore-Search-Version:
              $ref: "#/components/headers/XBenriscoreSearchVersion"
            X-Benriscore-Search-Sources:
              $ref: "#/components/headers/XBenriscoreSearchSources"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AskResponse"
        "400":
          $ref: "#/components/responses/InvalidParams"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
  /tiles/vector/{filename}:
    get:
      tags:
        - tiles
      summary: ベクタータイル 配信
      description: ベクタータイル を HTTP Range request で配信します。 Bearer 認証は不要 (browser 直 fetch 想定、 全 origin CORS)。 Range header は **必須** で、 過大な range や open-ended (`bytes=N-`) は拒否されます。
      operationId: getTile
      security: []
      parameters:
        - schema:
            type: string
            pattern: ^[a-z][a-z0-9_-]*\.pmtiles$
            description: ベクタータイルのファイル名です。 不正なファイル名は 400 で拒否されます。
            example: access-z15.pmtiles
          required: true
          description: ベクタータイルのファイル名です。 不正なファイル名は 400 で拒否されます。
          name: filename
          in: path
        - schema:
            type: string
            pattern: ^bytes=\d*-\d*$
            description: "必須です (例: `bytes=0-16383`)。 過大な range は拒否されます。"
            example: bytes=0-16383
          required: true
          description: "必須です (例: `bytes=0-16383`)。 過大な range は拒否されます。"
          name: Range
          in: header
      responses:
        "206":
          description: Range で指定された範囲のバイト列を返します。
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.pmtiles
            Content-Range:
              schema:
                type: string
                example: bytes 0-16383/12345678
            Content-Length:
              schema:
                type: integer
                example: 16384
            Accept-Ranges:
              schema:
                type: string
                example: bytes
            Cache-Control:
              schema:
                type: string
                example: public, max-age=86400, immutable
            X-Attribution:
              schema:
                type: string
                example: OpenStreetMap contributors (ODbL 1.0)
          content:
            application/vnd.pmtiles:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/InvalidParams"
        "404":
          $ref: "#/components/responses/NotFound"
  /tiles/archive/vector/{filename}:
    get:
      tags:
        - tiles-archive
      summary: ベクタータイル 配信 (過去バージョン archive 用)
      description: 過去バージョンの archive 専用 route です。 `/tiles/vector/{filename}` と挙動は同一です。
      operationId: getArchiveTile
      security: []
      parameters:
        - schema:
            type: string
            pattern: ^[a-z][a-z0-9_-]*\.pmtiles$
            description: ベクタータイルのファイル名です。 不正なファイル名は 400 で拒否されます。
            example: access-z15.pmtiles
          required: true
          description: ベクタータイルのファイル名です。 不正なファイル名は 400 で拒否されます。
          name: filename
          in: path
        - schema:
            type: string
            pattern: ^bytes=\d*-\d*$
          required: true
          name: Range
          in: header
      responses:
        "206":
          description: Range で指定された範囲のバイト列を返します (過去バージョン archive)。
          content:
            application/vnd.pmtiles:
              schema:
                type: string
                format: binary
        "400":
          $ref: "#/components/responses/InvalidParams"
        "404":
          $ref: "#/components/responses/NotFound"
  /mcp:
    post:
      tags:
        - mcp
      summary: MCP server (Model Context Protocol、 JSON-RPC 2.0)
      description: |-
        Claude Desktop / Cursor 等の MCP client から呼ばれる JSON-RPC endpoint。 Bearer 認証 + rate limit は REST と同じ枠を共有します (`/v1/point` 等と同じ上限)。

        対応 method:
        - `initialize` — server info + capabilities + protocolVersion
        - `notifications/initialized` — 200 (notification なので body なし)
        - `tools/list` — 利用可能 tool 一覧
        - `tools/call` — tool 実行 (利用可能 tool は `tools/list` を参照)
        - `ping` — 空 result

        認証失敗は HTTP error として返します。
      operationId: mcpJsonRpc
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/McpRequest"
      responses:
        "200":
          description: JSON-RPC 2.0 形式のレスポンスです。 notification (id なし request) の場合は空 body となります。
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/McpResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
    get:
      tags:
        - mcp
      summary: MCP GET
      description: GET /mcp は常に 405 Method Not Allowed を返します。
      operationId: mcpGet
      security: []
      responses:
        "405":
          description: Method Not Allowed です (POST のみ受け付けます)。
    delete:
      tags:
        - mcp
      summary: MCP DELETE
      description: DELETE /mcp は常に 405 Method Not Allowed を返します。
      operationId: mcpDelete
      security: []
      responses:
        "405":
          description: Method Not Allowed です (POST のみ受け付けます)。
webhooks: {}
