# Copyright 2021 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
openapi: 3.1.0
info:
  title: Matrix Client-Server Space Hierarchy API
  version: 1.0.0
paths:
  "/rooms/{roomId}/hierarchy":
    get:
      x-addedInMatrixVersion: "1.2"
      summary: Retrieve a portion of a space tree.
      description: |-
        Paginates over the space tree in a depth-first manner to locate child rooms of a given space.

        Where a child room is unknown to the local server, federation is used to fill in the details.
        The servers listed in the `via` array should be contacted to attempt to fill in missing rooms.

        Only [`m.space.child`](#mspacechild) state events of the room are considered. Invalid child
        rooms and parent events are not covered by this endpoint.
      operationId: getSpaceHierarchy
      security:
        - accessTokenQuery: []
        - accessTokenBearer: []
      parameters:
        - in: path
          name: roomId
          description: The room ID of the space to get a hierarchy for.
          required: true
          example: "!space:example.org"
          schema:
            type: string
        - in: query
          name: suggested_only
          description: |-
            Optional (default `false`) flag to indicate whether or not the server should only consider
            suggested rooms. Suggested rooms are annotated in their [`m.space.child`](#mspacechild) event
            contents.
          example: true
          schema:
            type: boolean
        - in: query
          name: limit
          description: |-
            Optional limit for the maximum number of rooms to include per response. Must be an integer
            greater than zero.

            Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
          example: 20
          schema:
            type: integer
        - in: query
          name: max_depth
          description: |-
            Optional limit for how far to go into the space. Must be a non-negative integer.

            When reached, no further child rooms will be returned.

            Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
          example: 5
          schema:
            type: integer
        - in: query
          name: from
          description: |-
            A pagination token from a previous result. If specified, `max_depth` and `suggested_only` cannot
            be changed from the first request.
          example: next_batch_token
          schema:
            type: string
      responses:
        "200":
          description: A portion of the space tree, starting at the provided room ID.
          content:
            application/json:
              schema:
                type: object
                properties:
                  rooms:
                    type: array
                    description: The rooms for the current page, with the current filters.
                    items:
                      allOf:
                        - $ref: definitions/public_rooms_chunk.yaml
                        - type: object
                          title: SpaceHierarchyRoomsChunk
                          properties:
                            room_type:
                              type: string
                              description: The `type` of room (from
                                [`m.room.create`](/client-server-api/#mroomcreate)),
                                if any.
                            children_state:
                              type: array
                              description: |-
                                The [`m.space.child`](#mspacechild) events of the space-room, represented
                                as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key.

                                If the room is not a space-room, this should be empty.
                              items:
                                allOf:
                                  - $ref: ../../event-schemas/schema/core-event-schema/stripped_state.yaml
                                  - type: object
                                    title: StrippedChildStateEvent
                                    properties:
                                      origin_server_ts:
                                        type: integer
                                        format: int64
                                        description: The `origin_server_ts` for the event.
                                    required:
                                      - origin_server_ts
                          required:
                            - children_state
                  next_batch:
                    type: string
                    description: |-
                      A token to supply to `from` to keep paginating the responses. Not present when there are
                      no further results.
                required:
                  - rooms
              examples:
                response:
                  value: {
                    "rooms": [
                      {
                        "room_id": "!space:example.org",
                        "avatar_url": "mxc://example.org/abcdef",
                        "guest_can_join": false,
                        "name": "The First Space",
                        "topic": "No other spaces were created first, ever",
                        "world_readable": true,
                        "join_rule": "public",
                        "room_type": "m.space",
                        "num_joined_members": 42,
                        "canonical_alias": "#general:example.org",
                        "children_state": [
                          {
                            "type": "m.space.child",
                            "state_key": "!a:example.org",
                            "content": {
                              "via": [
                                "example.org"
                              ]
                            },
                            "sender": "@alice:example.org",
                            "origin_server_ts": 1629413349153
                          }
                        ]
                      }
                    ],
                    "next_batch": "next_batch_token"
                  }
        "400":
          description: |-
            The request was invalid in some way. A meaningful `errcode`
            and description error text will be returned. Example reasons for rejection are:

            - The `from` token is unknown to the server.
            - `suggested_only` or `max_depth` changed during pagination.
          content:
            application/json:
              schema:
                $ref: definitions/errors/error.yaml
              examples:
                response:
                  value: {
                    "errcode": "M_INVALID_PARAM",
                    "error": "suggested_only and max_depth cannot change on paginated requests"
                  }
        "403":
          description: |-
            The user cannot view or peek on the room. A meaningful `errcode`
            and description error text will be returned. Example reasons for rejection are:

            - The room is not set up for peeking.
            - The user has been banned from the room.
            - The room does not exist.
          content:
            application/json:
              schema:
                $ref: definitions/errors/error.yaml
              examples:
                response:
                  value: {
                    "errcode": "M_FORBIDDEN",
                    "error": "You are not allowed to view this room."
                  }
        "429":
          description: This request was rate-limited.
          content:
            application/json:
              schema:
                $ref: definitions/errors/rate_limited.yaml
      tags:
        - Spaces
servers:
  - url: "{protocol}://{hostname}{basePath}"
    variables:
      protocol:
        enum:
          - http
          - https
        default: https
      hostname:
        default: localhost:8008
      basePath:
        default: /_matrix/client/v1
components:
  securitySchemes:
    accessTokenQuery:
      $ref: definitions/security.yaml#/accessTokenQuery
    accessTokenBearer:
      $ref: definitions/security.yaml#/accessTokenBearer
