# Copyright 2016, 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 sync API
  version: 1.0.0
paths:
  /sync:
    get:
      summary: Synchronise the client's state and receive new messages.
      description: |-
        Synchronise the client's state with the latest state on the server.
        Clients use this API when they first log in to get an initial snapshot
        of the state on the server, and then continue to call this API to get
        incremental deltas to the state, and to receive new messages.

        *Note*: This endpoint supports lazy-loading. See [Filtering](/client-server-api/#filtering)
        for more information. Lazy-loading members is only supported on a `StateFilter`
        for this endpoint. When lazy-loading is enabled, servers MUST include the
        syncing user's own membership event when they join a room, or when the
        full state of rooms is requested, to aid discovering the user's avatar &
        displayname.

        Further, like other members, the user's own membership event is eligible
        for being considered redundant by the server. When a sync is `limited`,
        the server MUST return membership events for events in the gap
        (between `since` and the start of the returned timeline), regardless
        as to whether or not they are redundant. This ensures that joins/leaves
        and profile changes which occur during the gap are not lost.

        Note that the default behaviour of `state` is to include all membership
        events, alongside other state, when lazy-loading is not enabled.
      operationId: sync
      security:
        - accessTokenQuery: []
        - accessTokenBearer: []
      parameters:
        - in: query
          name: filter
          description: |-
            The ID of a filter created using the filter API or a filter JSON
            object encoded as a string. The server will detect whether it is
            an ID or a JSON object by whether the first character is a `"{"`
            open brace. Passing the JSON inline is best suited to one off
            requests. Creating a filter using the filter API is recommended for
            clients that reuse the same filter multiple times, for example in
            long poll requests.

            See [Filtering](/client-server-api/#filtering) for more information.
          example: 66696p746572
          schema:
            type: string
        - in: query
          name: since
          description: |-
            A point in time to continue a sync from. This should be the
            `next_batch` token returned by an earlier call to this endpoint.
          example: s72594_4483_1934
          schema:
            type: string
        - in: query
          name: full_state
          description: |-
            Controls whether to include the full state for all rooms the user
            is a member of.

            If this is set to `true`, then all state events will be returned,
            even if `since` is non-empty. The timeline will still be limited
            by the `since` parameter. In this case, the `timeout` parameter
            will be ignored and the query will return immediately, possibly with
            an empty timeline.

            If `false`, and `since` is non-empty, only state which has
            changed since the point indicated by `since` will be returned.

            By default, this is `false`.
          example: false
          schema:
            type: boolean
        - in: query
          name: set_presence
          description: |-
            Controls whether the client is automatically marked as online by
            polling this API. If this parameter is omitted then the client is
            automatically marked as online when it uses this API. Otherwise if
            the parameter is set to "offline" then the client is not marked as
            being online when it uses this API. When set to "unavailable", the
            client is marked as being idle.
          example: offline
          schema:
            type: string
            enum:
              - offline
              - online
              - unavailable
        - in: query
          name: timeout
          description: |-
            The maximum time to wait, in milliseconds, before returning this
            request. If no events (or other data) become available before this
            time elapses, the server will return a response with empty fields.

            By default, this is `0`, so the server will return immediately
            even if the response is empty.
          example: 30000
          schema:
            type: integer
      responses:
        "200":
          description: The initial snapshot or delta for the client to use to update their
            state.
          content:
            application/json:
              schema:
                type: object
                properties:
                  next_batch:
                    type: string
                    description: |-
                      The batch token to supply in the `since` param of the next
                      `/sync` request.
                  rooms:
                    title: Rooms
                    type: object
                    description: Updates to rooms.
                    properties:
                      join:
                        title: Joined Rooms
                        type: object
                        description: |-
                          The rooms that the user has joined, mapped as room ID to
                          room information.
                        patternProperties:
                          "^!":
                            x-pattern-format: mx-room-id
                            title: Joined Room
                            type: object
                            properties:
                              summary:
                                title: RoomSummary
                                type: object
                                description: |-
                                  Information about the room which clients may need to
                                  correctly render it to users.
                                properties:
                                  m.heroes:
                                    type: array
                                    description: |-
                                      The users which can be used to generate a room name
                                      if the room does not have one. Required if the room's
                                      `m.room.name` or `m.room.canonical_alias` state events
                                      are unset or empty.

                                      This should be the first 5 members of the room, ordered
                                      by stream ordering, which are joined or invited. The
                                      list must never include the client's own user ID. When
                                      no joined or invited members are available, this should
                                      consist of the banned and left users. More than 5 members
                                      may be provided, however less than 5 should only be provided
                                      when there are less than 5 members to represent.

                                      When lazy-loading room members is enabled, the membership
                                      events for the heroes MUST be included in the `state`,
                                      unless they are redundant. When the list of users changes,
                                      the server notifies the client by sending a fresh list of
                                      heroes. If there are no changes since the last sync, this
                                      field may be omitted.
                                    items:
                                      type: string
                                  m.joined_member_count:
                                    type: integer
                                    description: |-
                                      The number of users with `membership` of `join`,
                                      including the client's own user ID. If this field has
                                      not changed since the last sync, it may be omitted.
                                      Required otherwise.
                                  m.invited_member_count:
                                    type: integer
                                    description: |-
                                      The number of users with `membership` of `invite`.
                                      If this field has not changed since the last sync, it
                                      may be omitted. Required otherwise.
                              state:
                                title: State
                                type: object
                                description: |-
                                  Updates to the state, between the time indicated by
                                  the `since` parameter, and the start of the
                                  `timeline` (or all state up to the start of the
                                  `timeline`, if `since` is not given, or
                                  `full_state` is true).

                                  N.B. state updates for `m.room.member` events will
                                  be incomplete if `lazy_load_members` is enabled in
                                  the `/sync` filter, and only return the member events
                                  required to display the senders of the timeline events
                                  in this response.
                                allOf:
                                  - $ref: definitions/state_event_batch.yaml
                              timeline:
                                title: Timeline
                                type: object
                                description: |-
                                  The timeline of messages and state changes in the
                                  room.
                                allOf:
                                  - $ref: definitions/timeline_batch.yaml
                              ephemeral:
                                title: Ephemeral
                                type: object
                                description: |-
                                  The new ephemeral events in the room (events that
                                  aren't recorded in the timeline or state of the
                                  room). In this version of the spec, these are
                                  [typing notification](#typing-notifications) and
                                  [read receipt](#receipts) events.
                                allOf:
                                  - $ref: definitions/event_batch.yaml
                              account_data:
                                title: Account Data
                                type: object
                                description: |-
                                  The private data that this user has attached to
                                  this room.
                                allOf:
                                  - $ref: definitions/event_batch.yaml
                              unread_notifications:
                                title: Unread Notification Counts
                                type: object
                                description: |-
                                  Counts of unread notifications for this room. See the
                                  [Receiving notifications](/client-server-api/#receiving-notifications) section
                                  for more information on how these are calculated.

                                  If `unread_thread_notifications` was specified as `true` on the `RoomEventFilter`,
                                  these counts will only be for the main timeline rather than all events in the room.
                                  See the [threading module](#threading) for more information.
                                x-changedInMatrixVersion:
                                  "1.4": |
                                    Updated to reflect behaviour of having `unread_thread_notifications` as `true` in
                                    the `RoomEventFilter` for `/sync`.
                                properties:
                                  highlight_count:
                                    title: Highlighted notification count
                                    type: integer
                                    description: The number of unread notifications for this room with the highlight
                                      flag set.
                                  notification_count:
                                    title: Total notification count
                                    type: integer
                                    description: The total number of unread notifications for this room.
                              unread_thread_notifications:
                                title: Unread Thread Notification Counts
                                type: object
                                description: |-
                                  If `unread_thread_notifications` was specified as `true` on the `RoomEventFilter`,
                                  the notification counts for each [thread](#threading) in this room. The object is
                                  keyed by thread root ID, with values matching `unread_notifications`.

                                  If a thread does not have any notifications it can be omitted from this object. If
                                  no threads have notification counts, this whole object can be omitted.
                                x-addedInMatrixVersion: "1.4"
                                patternProperties:
                                  "^\\$":
                                    x-pattern-format: mx-event-id
                                    title: ThreadNotificationCounts
                                    type: object
                                    properties:
                                      highlight_count:
                                        title: ThreadedHighlightNotificationCount
                                        type: integer
                                        description: The number of unread notifications for this *thread* with the
                                          highlight flag set.
                                      notification_count:
                                        title: ThreadedTotalNotificationCount
                                        type: integer
                                        description: The total number of unread notifications for this *thread*.
                      invite:
                        title: Invited Rooms
                        type: object
                        description: |-
                          The rooms that the user has been invited to, mapped as room ID to
                          room information.
                        patternProperties:
                          "^!":
                            x-pattern-format: mx-room-id
                            title: Invited Room
                            type: object
                            properties:
                              invite_state:
                                title: InviteState
                                type: object
                                description: |-
                                  The [stripped state](#stripped-state) of a room that the user has been invited
                                  to.
                                properties:
                                  events:
                                    description: The [stripped state events](#stripped-state) that form the invite
                                      state.
                                    items:
                                      $ref: ../../event-schemas/schema/core-event-schema/stripped_state.yaml
                                    type: array
                      knock:
                        title: Knocked rooms
                        type: object
                        description: The rooms that the user has knocked upon, mapped as room ID to room
                          information.
                        patternProperties:
                          "^!":
                            x-pattern-format: mx-room-id
                            title: Knocked Room
                            type: object
                            properties:
                              knock_state:
                                title: KnockState
                                type: object
                                description: The [stripped state](#stripped-state) of a room that the user has
                                  knocked upon.
                                properties:
                                  events:
                                    description: The [stripped state events](#stripped-state) that form the knock
                                      state.
                                    items:
                                      $ref: ../../event-schemas/schema/core-event-schema/stripped_state.yaml
                                    type: array
                      leave:
                        title: Left rooms
                        type: object
                        description: |-
                          The rooms that the user has left or been banned from, mapped as room ID to
                          room information.
                        patternProperties:
                          "^!":
                            x-pattern-format: mx-room-id
                            title: Left Room
                            type: object
                            properties:
                              state:
                                title: State
                                type: object
                                description: The state updates for the room up to the start of the timeline.
                                allOf:
                                  - $ref: definitions/state_event_batch.yaml
                              timeline:
                                title: Timeline
                                type: object
                                description: |-
                                  The timeline of messages and state changes in the
                                  room up to the point when the user left.
                                allOf:
                                  - $ref: definitions/timeline_batch.yaml
                              account_data:
                                title: Account Data
                                type: object
                                description: |-
                                  The private data that this user has attached to
                                  this room.
                                allOf:
                                  - $ref: definitions/event_batch.yaml
                  presence:
                    title: Presence
                    type: object
                    description: The updates to the presence status of other users.
                    allOf:
                      - $ref: definitions/event_batch.yaml
                  account_data:
                    title: Account Data
                    type: object
                    description: The global private data created by this user.
                    allOf:
                      - $ref: definitions/event_batch.yaml
                  to_device:
                    title: ToDevice
                    type: object
                    description: |-
                      Information on the send-to-device messages for the client
                      device, as defined in [Send-to-Device messaging](/client-server-api/#extensions-to-sync).
                  device_lists:
                    title: DeviceLists
                    type: object
                    description: |-
                      Information on end-to-end device updates, as specified in
                      [End-to-end encryption](/client-server-api/#e2e-extensions-to-sync).
                  device_one_time_keys_count:
                    title: One-time keys count
                    type: object
                    additionalProperties:
                      type: integer
                    description: |-
                      Information on end-to-end encryption keys, as specified
                      in [End-to-end encryption](/client-server-api/#e2e-extensions-to-sync).
                required:
                  - next_batch
              examples:
                response:
                  value: {
                    "next_batch": "s72595_4483_1934",
                    "presence": {
                      "events": [
                        {
                          "$ref": "../../event-schemas/examples/m.presence.yaml"
                        }
                      ]
                    },
                    "account_data": {
                      "events": [
                        {
                          "type": "org.example.custom.config",
                          "content": {
                            "custom_config_key": "custom_config_value"
                          }
                        }
                      ]
                    },
                    "rooms": {
                      "join": {
                        "!726s6s6q:example.com": {
                          "summary": {
                            "m.heroes": [
                              "@alice:example.com",
                              "@bob:example.com"
                            ],
                            "m.joined_member_count": 2,
                            "m.invited_member_count": 0
                          },
                          "state": {
                            "events": [
                              {
                                "$ref": "../../event-schemas/examples/m.room.member.yaml"
                              }
                            ]
                          },
                          "timeline": {
                            "events": [
                              {
                                "$ref": "../../event-schemas/examples/m.room.member.yaml"
                              },
                              {
                                "$ref": "../../event-schemas/examples/m.room.message$m.text.yaml"
                              }
                            ],
                            "limited": true,
                            "prev_batch": "t34-23535_0_0"
                          },
                          "ephemeral": {
                            "events": [
                              {
                                "$ref": "../../event-schemas/examples/m.typing.yaml"
                              },
                              {
                                "$ref": "../../event-schemas/examples/m.receipt.yaml"
                              }
                            ]
                          },
                          "account_data": {
                            "events": [
                              {
                                "$ref": "../../event-schemas/examples/m.tag.yaml"
                              },
                              {
                                "type": "org.example.custom.room.config",
                                "content": {
                                  "custom_config_key": "custom_config_value"
                                }
                              }
                            ]
                          },
                          "unread_notifications": {
                            "highlight_count": 1,
                            "notification_count": 5
                          },
                          "unread_thread_notifications": {
                            "$threadroot": {
                              "highlight_count": 3,
                              "notification_count": 6
                            }
                          }
                        }
                      },
                      "invite": {
                        "!696r7674:example.com": {
                          "invite_state": {
                            "events": [
                              {
                                "sender": "@alice:example.com",
                                "type": "m.room.name",
                                "state_key": "",
                                "content": {
                                  "name": "My Room Name"
                                }
                              },
                              {
                                "sender": "@alice:example.com",
                                "type": "m.room.member",
                                "state_key": "@bob:example.com",
                                "content": {
                                  "membership": "invite"
                                }
                              }
                            ]
                          }
                        }
                      },
                      "knock": {
                        "!223asd456:example.com": {
                          "knock_state": {
                            "events": [
                              {
                                "sender": "@alice:example.com",
                                "type": "m.room.name",
                                "state_key": "",
                                "content": {
                                  "name": "My Room Name"
                                }
                              },
                              {
                                "sender": "@bob:example.com",
                                "type": "m.room.member",
                                "state_key": "@bob:example.com",
                                "content": {
                                  "membership": "knock"
                                }
                              }
                            ]
                          }
                        }
                      },
                      "leave": {}
                    }
                  }
      tags:
        - Room participation
servers:
  - url: "{protocol}://{hostname}{basePath}"
    variables:
      protocol:
        enum:
          - http
          - https
        default: https
      hostname:
        default: localhost:8008
      basePath:
        default: /_matrix/client/v3
components:
  securitySchemes:
    accessTokenQuery:
      $ref: definitions/security.yaml#/accessTokenQuery
    accessTokenBearer:
      $ref: definitions/security.yaml#/accessTokenBearer
