# This file contains the API definitions for the Zulip REST API.
#
# For details on the OpenAPI specification, see https://swagger.io/specification
#
# Our own documentation lives at
#
#   https://zulip.readthedocs.io/en/latest/documentation/openapi.html
#

openapi: 3.0.1
info:
  version: 1.0.0
  title: Zulip REST API
  description: |
    Powerful open source group chat
  contact:
    url: https://zulip.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  # Zulip Cloud
  - url: "https://{subdomain}.zulipchat.com/api/v1"
    variables:
      subdomain:
        default: example
  # Self-hosted
  - url: "{server}/api/v1"
    variables:
      server:
        default: https://
  # chat.zulip.org
  - url: "https://chat.zulip.org/api/v1"
  # Development server
  - url: "http://localhost:9991/api/v1"
security:
  - basicAuth: []
#######################
# Endpoint definitions
#######################
paths:
  /fetch_api_key:
    post:
      operationId: fetch_api_key
      tags: ["authentication"]
      description: |
        Given a username and password, fetch the user's API key.

        Used to authenticate the mobile and terminal apps when the server
        has EmailAuthBackend or LDAPAuthBackend enabled.
      parameters:
        - name: username
          in: query
          description: |
            The username to be used for authentication (typically, the email
            address, but it could be an LDAP username).
          schema:
            type: string
          required: true
        - name: password
          in: query
          schema:
            type: string
          description: |
            The user's Zulip password (or LDAP password, if LDAP authentication is in use).
          required: true
      responses:
        "200":
          description: The credentials needed to use the Zulip API.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiKeyResponse"
  /dev_fetch_api_key:
    post:
      operationId: dev_fetch_api_key
      tags: ["authentication"]
      description: |
        For easy testing of mobile apps and other clients and against Zulip
        development servers, we support fetching a Zulip API key for any user
        on the development server without authentication (so that they can
        implement analogues of the one-click login process available for Zulip
        development servers on the web).

        **Note:** This endpoint is only available on Zulip development
        servers; for obvious security reasons it will always return an error
        in a Zulip production server.

        `POST {{ api_url }}/v1/dev_fetch_api_key`
      parameters:
        - name: username
          in: query
          description: |
            The email address for the user that owns the API key.
          schema:
            type: string
          example: iago@zulip.com
          required: true
      security: []
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiKeyResponse"
  /events:
    get:
      operationId: get_events
      tags: ["real_time_events"]
      description: |
        `GET {{ api_url }}/v1/events`

        This endpoint allows you to receive new events from
        [a registered event queue](/api/register-queue).
      parameters:
        - $ref: "#/components/parameters/QueueId"
        - name: last_event_id
          in: query
          description: |
            The highest event ID in this queue that you've received and
            wish to acknowledge. See the [code for
            `call_on_each_event`](https://github.com/zulip/python-zulip-api/blob/master/zulip/zulip/__init__.py)
            in the [zulip Python
            module](https://github.com/zulip/python-zulip-api) for an
            example implementation of correctly processing each event
            exactly once.
          schema:
            type: integer
          example: -1
        - name: dont_block
          in: query
          description: |
            Set to `true` if the client is requesting a nonblocking reply. If not
            specified, the request will block until either a new event is available
            or a few minutes have passed, in which case the server will send the
            client a heartbeat event.
          schema:
            type: boolean
            default: false
          example: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      events:
                        type: array
                        description: |
                          An array of `event` objects (possibly zero-length if `dont_block` is
                          set) with IDs newer than `last_event_id`. Event IDs are
                          guaranteed to be increasing, but they are not guaranteed to be
                          consecutive.
                        items:
                          type: object
                          additionalProperties: false
                      queue_id:
                        type: string
                        description: |
                          The ID of the registered queue.
                  - example:
                      {
                        "queue_id": "1375801870:2942",
                        "events":
                          [
                            {
                              "id": 0,
                              "message":
                                {
                                  "avatar_url": "https://url/for/othello-bots/avatar",
                                  "client": "website",
                                  "content": "I come not, friends, to steal away your hearts.",
                                  "content_type": "text/x-markdown",
                                  "display_recipient": "Denmark",
                                  "id": 12345678,
                                  "recipient_id": 12314,
                                  "sender_email": "othello-bot@example.com",
                                  "sender_full_name": "Othello Bot",
                                  "sender_id": 13215,
                                  "sender_realm_str": "example",
                                  "topic": "Castle",
                                  "topic_links": [],
                                  "timestamp": 1375978403,
                                  "type": "stream",
                                },
                              "type": "message",
                            },
                            {
                              "id": 1,
                              "message":
                                {
                                  "avatar_url": "https://url/for/othello-bots/avatar",
                                  "client": "website",
                                  "content": "With mirth and laughter let old wrinkles come.",
                                  "content_type": "text/x-markdown",
                                  "display_recipient":
                                    [
                                      {
                                        "email": "hamlet@example.com",
                                        "full_name": "Hamlet of Denmark",
                                        "id": 31572,
                                      },
                                    ],
                                  "id": 12345679,
                                  "recipient_id": 18391,
                                  "sender_email": "othello-bot@example.com",
                                  "sender_full_name": "Othello Bot",
                                  "sender_id": 13215,
                                  "sender_realm_str": "example",
                                  "subject": "",
                                  "topic_links": [],
                                  "timestamp": 1375978404,
                                  "type": "private",
                                },
                              "type": "message",
                            },
                          ],
                        "msg": "",
                        "result": "success",
                      }
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BadEventQueueIdError"
    delete:
      operationId: delete_queue
      tags: ["real_time_events"]
      description: |
        Delete a previously registered queue.

        `DELETE {{ api_url }}/v1/events`
      parameters:
        - $ref: "#/components/parameters/QueueId"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BadEventQueueIdError"
  /get_stream_id:
    get:
      operationId: get_stream_id
      tags: ["streams"]
      description: |
        Get the unique ID of a given stream.

        `GET {{ api_url }}/v1/get_stream_id`
      parameters:
        - $ref: "#/components/parameters/Stream"
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      stream_id:
                        type: integer
                        description: |
                          The ID of the given stream.
                  - example: {"msg": "", "result": "success", "stream_id": 15}
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/CodedError"
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "Invalid stream name 'nonexistent'",
                        "result": "error",
                      }
  /mark_all_as_read:
    post:
      operationId: mark_all_as_read
      tags: ["messages"]
      description: |
        Marks all of the current user's unread messages as read.

        `POST {{ api_url }}/v1/mark_all_as_read`
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
  /mark_stream_as_read:
    post:
      operationId: mark_stream_as_read
      tags: ["messages"]
      description: |
        Mark all the unread messages in a stream as read.
      parameters:
        - $ref: "#/components/parameters/StreamIdInQuery"
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
  /mark_topic_as_read:
    post:
      operationId: mark_topic_as_read
      tags: ["messages"]
      description: |
        Mark all the unread messages in a topic as read.
      parameters:
        - $ref: "#/components/parameters/StreamIdInQuery"
          required: true
        - name: topic_name
          in: query
          description: |
            The name of the topic whose messages should be marked as read.
          schema:
            type: string
          example: new coffee machine
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
  /attachments:
    get:
      operationId: get_attachments
      tags: ["users"]
      description: |
        Fetch metadata on files uploaded by the requesting user.

        `GET {{ api_url }}/v1/attachments`
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      attachments:
                        type: array
                        description: |
                          A list of `attachment` objects, each containing
                          details about a file uploaded by the user.
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            id:
                              type: integer
                              description: |
                                The unique ID for the attachment.
                            name:
                              type: string
                              description: |
                                Name of the uploaded file.
                            path_id:
                              type: string
                              description: |
                                A representation of the path of the file within the
                                repository of user-uploaded files.  If the `path_id` of a
                                file is `{realm_id}/ab/cdef/temp_file.py`, its URL will be:
                                `{server_url}/user_uploads/{realm_id}/ab/cdef/temp_file.py`.
                            size:
                              type: integer
                              description: |
                                Size of the file in bytes.
                            create_time:
                              type: integer
                              description: |
                                Time when the attachment was uploaded as a UNIX timestamp
                                multiplied by 1000 (matching the format of getTime() in JavaScript).

                                **Changes**: Changed in Zulip 2.2 (feature level 22).  This field was
                                previously a floating point number.
                            messages:
                              type: array
                              description: |
                                Contains basic details on any Zulip messages that have been
                                sent referencing this [uploaded file](/api/upload-file).
                                This includes messages sent by any user in the Zulip
                                organization who sent a message containing a link to the
                                uploaded file.
                              items:
                                type: object
                                additionalProperties: false
                                properties:
                                  date_sent:
                                    type: integer
                                    description: |
                                      Time when the message was sent as a UNIX timestamp
                                      multiplied by 1000 (matching the format of getTime() in JavaScript).

                                      **Changes**: Changed in Zulip 2.2 (feature level 22).  This
                                      field was previously strangely called `name` and was a floating
                                      point number.
                                  id:
                                    type: integer
                                    description: |
                                      The unique message ID.  Messages should always be
                                      displayed sorted by ID.
                      upload_space_used:
                        type: integer
                        description: |
                          The total size of all files uploaded by in the organization,
                          in bytes.
                  - example:
                      {
                        "result": "success",
                        "msg": "",
                        "attachments":
                          [
                            {
                              "id": 1,
                              "name": "166050.jpg",
                              "path_id": "2/ce/DfOkzwdg_IwlrN3myw3KGtiJ/166050.jpg",
                              "size": 571946,
                              "create_time": 1588145417000,
                              "messages":
                                [
                                  {"id": 102, "date_sent": 1588145424000},
                                  {"id": 103, "date_sent": 1588145448000},
                                ],
                            },
                          ],
                        "upload_space_used": 571946,
                      }
  /messages:
    get:
      operationId: get_messages
      tags: ["messages"]
      description: |
        Fetch message history from a Zulip server.

        `GET {{ api_url }}/v1/messages`

        This `GET /api/v1/messages` endpoint is the primary way to fetch
        message history from a Zulip server.  It is useful both for Zulip
        clients (e.g. the web, desktop, mobile, and terminal clients) as well
        as bots, API clients, backup scripts, etc.

        By specifying a [narrow filter](/api/construct-narrow), you can use
        this endpoint to fetch the messages matching any search query that is
        supported by Zulip's powerful full-text search backend.

        When a narrow is not specified, it can be used to fetch a user's
        message history (We recommend paginating to 1000 messages at a time).

        In either case, you specify an `anchor` message (or ask the server to
        calculate the first unread message for you and use that as the
        anchor), as well as a number of messages before and after the anchor
        message.  The server returns those messages, sorted by message ID, as
        well as some metadata that makes it easy for a client to determine
        whether there are more messages matching the query that were not
        returned due to the `num_before` and `num_after` limits.

        We recommend using `num_before <= 1000` and `num_after <= 1000` to
        avoid generating very large HTTP responses. A maximum of 5000 messages
        can be obtained per request; attempting to exceed this will result in an
        error.
      parameters:
        - name: anchor
          in: query
          description: |
            Integer message ID to anchor fetching of new messages. Supports special
            string values for when the client wants the server to compute the anchor
            to use:

            * `newest`: The most recent message.
            * `oldest`: The oldest message.
            * `first_unread`: The oldest unread message matching the
              query, if any; otherwise, the most recent message.

            The special values of `'newest'` and `'oldest'` are also supported
            for anchoring the query at the most recent or oldest messages.

            **Changes**: String values are new in Zulip 3.0 (feature level 1).  The
              `first_unread` functionality was supported in Zulip 2.1.x
              and older by not sending anchor and using use_first_unread_anchor.

              In Zulip 2.1.x and older, `oldest` can be emulated with
              `anchor=0`, and `newest` with `anchor=10000000000000000`
              (that specific large value works around a bug in Zulip
              2.1.x and older in the `found_newest` return value).
          schema:
            oneOf:
              - type: string
              - type: integer
          example: 42
        - name: num_before
          in: query
          description: |
            The number of messages with IDs less than the anchor to retrieve.
          schema:
            type: integer
            minimum: 0
          example: 4
          required: true
        - name: num_after
          in: query
          description: |
            The number of messages with IDs greater than the anchor to retrieve.
          schema:
            type: integer
            minimum: 0
          example: 8
          required: true
        - name: narrow
          in: query
          description: |
            The narrow where you want to fetch the messages from. See how to
            [construct a narrow](/api/construct-narrow).
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                default: []
              example: [{"operand": "Denmark", "operator": "stream"}]
        - $ref: "#/components/parameters/ClientGravatar"
        - name: apply_markdown
          in: query
          description: |
            If `true`, message content is returned in the rendered HTML
            format. If `false`, message content is returned in the raw
            markdown-format text that user entered.
          schema:
            type: boolean
            default: true
          example: false
        - name: use_first_unread_anchor
          in: query
          deprecated: true
          description: |
            Legacy way to specify `anchor="first_unread"` in Zulip 2.1.x and older.

            Whether to use the (computed by the server) first unread message
            matching the narrow as the `anchor`.  Mutually exclusive with `anchor`.

            **Changes**: Deprecated in Zulip 3.0, replaced by
            `anchor="first_unread"` instead.
          schema:
            type: boolean
            default: false
          example: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      anchor:
                        type: integer
                        description: |
                          The same `anchor` specified in the request (or the computed one, if
                          `use_first_unread_anchor` is `true`).
                      found_newest:
                        type: boolean
                        description: |
                          Whether the `messages` list includes the very newest messages matching
                          the narrow (used by clients that paginate their requests to decide
                          whether there are more messages to fetch).
                      found_oldest:
                        type: boolean
                        description: |
                          Whether the `messages` list includes the very oldest messages matching
                          the narrow (used by clients that paginate their requests to decide
                          whether there are more messages to fetch).
                      found_anchor:
                        type: boolean
                        description: |
                          Whether the anchor message is included in the
                          response. If the message with the ID specified
                          in the request does not exist or did not match
                          the narrow, this will be false.
                      history_limited:
                        type: boolean
                        description: |
                          Whether the message history was limited due to
                          plan restrictions. This flag is set to `true`
                          only when the oldest messages(`found_oldest`)
                          matching the narrow is fetched.
                      messages:
                        type: array
                        description: |
                          an array of `message` objects, each containing the following
                          fields:
                        items:
                          $ref: "#/components/schemas/Messages"
                  - example:
                      {
                        "anchor": 21,
                        "found_newest": true,
                        "found_anchor": true,
                        "result": "success",
                        "msg": "",
                        "messages":
                          [
                            {
                              "subject": "",
                              "sender_realm_str": "zulip",
                              "type": "private",
                              "content": "<p>Security experts agree that relational algorithms are an interesting new topic in the field of networking, and scholars concur.</p>",
                              "flags": ["read"],
                              "id": 16,
                              "display_recipient":
                                [
                                  {
                                    "id": 4,
                                    "is_mirror_dummy": false,
                                    "email": "hamlet@zulip.com",
                                    "full_name": "King Hamlet",
                                  },
                                  {
                                    "id": 5,
                                    "is_mirror_dummy": false,
                                    "email": "iago@zulip.com",
                                    "full_name": "Iago",
                                  },
                                  {
                                    "id": 8,
                                    "is_mirror_dummy": false,
                                    "email": "prospero@zulip.com",
                                    "full_name": "Prospero from The Tempest",
                                  },
                                ],
                              "content_type": "text/html",
                              "is_me_message": false,
                              "timestamp": 1527921326,
                              "sender_id": 4,
                              "sender_full_name": "King Hamlet",
                              "recipient_id": 27,
                              "topic_links": [],
                              "client": "populate_db",
                              "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
                              "submessages": [],
                              "sender_email": "hamlet@zulip.com",
                              "reactions": [],
                            },
                            {
                              "subject": "Verona3",
                              "stream_id": 5,
                              "sender_realm_str": "zulip",
                              "type": "stream",
                              "content": "<p>Wait, is this from the frontend js code or backend python code</p>",
                              "flags": ["read"],
                              "id": 21,
                              "display_recipient": "Verona",
                              "content_type": "text/html",
                              "is_me_message": false,
                              "timestamp": 1527939746,
                              "sender_id": 4,
                              "sender_full_name": "King Hamlet",
                              "recipient_id": 20,
                              "topic_links": [],
                              "client": "populate_db",
                              "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
                              "submessages": [],
                              "sender_email": "hamlet@zulip.com",
                              "reactions": [],
                            },
                          ],
                      }
    post:
      operationId: send_message
      tags: ["messages"]
      description: |
        Send a stream or a private message.

        `POST {{ api_url }}/v1/messages`
      parameters:
        - name: type
          in: query
          description: |
            The type of message to be sent. `private` for a private message and
            `stream` for a stream message.
          schema:
            type: string
            enum:
              - private
              - stream
          example: private
          required: true
        - name: to
          in: query
          description: |
            For stream messages, either the name or integer ID of the stream. For
            private messages, either a list containing integer user IDs or a list
            containing string email addresses.

            **Changes**: Support for using user/stream IDs was added in Zulip 2.0.0.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
              example: [9, 10]
          required: true
        - $ref: "#/components/parameters/RequiredContent"
        - $ref: "#/components/parameters/Topic"
        - name: queue_id
          in: query
          schema:
            type: string
          description: |
            For clients supporting
            [local echo](https://zulip.readthedocs.io/en/latest/subsystems/sending-messages.html#local-echo),
            the [event queue](/api/register-queue)
            ID for the client.  If passed, `local_id` is required.  If the message is
            successfully sent, the server will include `local_id` in the `message` event
            that the client with this `queue_id` will receive notifying it of the new message
            via [`GET /events`](/api/get-events).  This lets the client know unambiguously
            that it should replace the locally echoed message, rather than adding this new
            message (which would be correct if the user had sent the new message from another
            device).
          example: "1593114627:0"
        - name: local_id
          in: query
          schema:
            type: string
          description: |
            For clients supporting local echo, a unique string-format identifier
            chosen freely by the client; the server will pass it back to the client without
            inspecting it, as described in the `queue_id` description.
          example: "100.01"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      id:
                        type: integer
                        description: |
                          The unique ID assigned to the sent message.
                      deliver_at:
                        type: string
                        description: |
                          Present for scheduled messages, encodes the time when the message will
                          be sent.  Note that scheduled messages ("Send later") is a beta API and
                          may change before it's a finished feature.
                        example: "2020-06-24 11:19:54.337533+00:00"
                  - example: {"msg": "", "id": 42, "result": "success"}
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/NonExistingStreamError"
                  - allOf:
                      - $ref: "#/components/schemas/CodedError"
                      - example:
                          {
                            "code": "BAD_REQUEST",
                            "msg": "Invalid email 'eeshan@zulip.com'",
                            "result": "error",
                          }
  /messages/{message_id}/history:
    get:
      operationId: get_message_history
      tags: ["messages"]
      description: |
        Fetch the message edit history of a previously edited message.

        `GET {{ api_url }}/v1/messages/{message_id}/history`

        Note that edit history may be disabled in some organizations; see the
        [Zulip Help Center documentation on editing messages][edit-settings].

        [edit-settings]: /help/view-a-messages-edit-history
      parameters:
        - $ref: "#/components/parameters/MessageId"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      message_history:
                        type: array
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            topic:
                              type: string
                              description: |
                                the topic for the message.
                            prev_topic:
                              type: string
                              description: |
                                the topic for the message before being edited.
                            content:
                              type: string
                              description: |
                                the body of the message.
                            rendered_content:
                              type: string
                              description: |
                                the already rendered, HTML version of `content`.
                            prev_content:
                              type: string
                              description: |
                                the body of the message before being edited.
                            prev_rendered_content:
                              type: string
                              description: |
                                the already rendered, HTML version of
                                `prev_content`.
                            user_id:
                              type: integer
                              description: |
                                the ID of the user that made the edit.
                            content_html_diff:
                              type: string
                              description: |
                                an HTML diff between this version of the message
                                and the previous one.
                            timestamp:
                              type: integer
                              description: |
                                the UNIX timestamp for this edit.
                        description: |
                          A chronologically sorted array of `snapshot`
                          objects, each one with the values of the
                          message after the edit.
                  - example:
                      {
                        "message_history":
                          [
                            {
                              "content": "Hello!",
                              "topic": "party at my houz",
                              "rendered_content": "<p>Hello!</p>",
                              "timestamp": 1530129122,
                              "user_id": 5,
                            },
                            {
                              "topic": "party at my house",
                              "content": "Howdy!",
                              "prev_content": "Hello!",
                              "rendered_content": "<p>Howdy!</p>",
                              "user_id": 5,
                              "prev_rendered_content": "<p>Hello!</p>",
                              "content_html_diff": '<div><p><span class="highlight_text_inserted">Howdy!</span></p> <p><span class="highlight_text_deleted">Hello!</span></p></div>',
                              "prev_topic": "party at my houz",
                              "timestamp": 1530129134,
                            },
                          ],
                        "msg": "",
                        "result": "success",
                      }
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvalidMessageError"
  /messages/flags:
    post:
      operationId: update_message_flags
      tags: ["messages"]
      description: |
        Add or remove personal message flags like `read` and `starred`
        on a collection of message IDs.

        `POST {{ api_url }}/v1/messages/flags`

        For updating the `read` flag on common collections of messages, see also
        the
        [special endpoints for marking message as read in bulk](/api/mark-all-as-read).
      parameters:
        - name: messages
          in: query
          description: |
            An array containing the IDs of the target messages.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
              example: [4, 8, 15]
          required: true
        - name: op
          in: query
          description: |
            Whether to `add` the flag or `remove` it.
          schema:
            type: string
            enum:
              - add
              - remove
          example: add
          required: true
        - name: flag
          in: query
          description: |
            The flag that should be added/removed.
          schema:
            type: string
          example: read
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      messages:
                        type: array
                        items:
                          type: integer
                        description: |
                          An array with the IDs of the modified messages.
                  - example:
                      {"msg": "", "messages": [4, 18, 15], "result": "success"}
  /messages/render:
    post:
      operationId: render_message
      tags: ["messages"]
      description: |
        Render a message to HTML.

        `POST {{ api_url }}/v1/messages/render`
      parameters:
        - $ref: "#/components/parameters/RequiredContent"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      rendered:
                        type: string
                        description: |
                          The rendered HTML.
                  - example:
                      {
                        "msg": "",
                        "rendered": "<p><strong>foo</strong></p>",
                        "result": "success",
                      }
  /messages/{message_id}/reactions:
    post:
      operationId: add_reaction
      tags: ["messages"]
      description: |
        Add an [emoji reaction](/help/emoji-reactions) to a message.

        `POST {{ api_url }}/v1/messages/{message_id}/reactions`
      parameters:
        - $ref: "#/components/parameters/MessageId"
        - $ref: "#/components/parameters/EmojiName"
          required: true
        - $ref: "#/components/parameters/EmojiCode"
        - $ref: "#/components/parameters/ReactionType"
      responses:
        "200":
          $ref: "#/components/responses/SimpleSuccess"

        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/CodedError"
                  - example:
                      {
                        "result": "error",
                        "msg": "Invalid emoji code",
                        "code": "BAD_REQUEST",
                      }

    delete:
      operationId: remove_reaction
      tags: ["messages"]
      description: |
        Remove an [emoji reaction](/help/emoji-reactions) from a message.

        `DELETE {{ api_url }}/v1/messages/{message_id}/reactions`
      parameters:
        - $ref: "#/components/parameters/MessageId"
        - $ref: "#/components/parameters/EmojiName"
          required: false
        - $ref: "#/components/parameters/EmojiCode"
        - $ref: "#/components/parameters/ReactionType"
      responses:
        "200":
          $ref: "#/components/responses/SimpleSuccess"
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/CodedError"
                  - example:
                      {
                        "result": "error",
                        "msg": "Invalid message(s)",
                        "code": "BAD_REQUEST",
                      }
  /messages/matches_narrow:
    get:
      operationId: check_messages_match_narrow
      tags: ["messages"]
      description: |
        Check whether a set of messages match a [narrow](/api/construct-narrow).

        `GET {{ api_url }}/v1/messages/matches_narrow`

        For many common narrows (E.g. a topic), clients can write an
        efficient client-side check to determine whether a
        newly arrived message belongs in the view.

        This endpoint is designed to allow clients to handle more complex narrows
        for which the client does not (or in the case of full-text search,
        cannot) implement this check.

        The format of the `match_subject` and `match_content` objects is designed to match
        those of `GET /messages`, so that a client can splice these fields into a
        `message` object received from `GET /events` and end up with an extended message
        object identical to how a `GET /messages` for the current narrow would have
        returned the message.
      parameters:
        - name: msg_ids
          in: query
          description: List of IDs for the messages to check.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
              example: [31, 32]
          required: true
        - name: narrow
          in: query
          description:
            A structure defining the narrow to check against. See how to
            [construct a narrow](/api/construct-narrow).
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example: [{"operator": "has", "operand": "link"}]
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      messages:
                        type: object
                        description: |
                          A dictionary with a key for each queried message that matches the narrow,
                          with message IDs as keys and search rendering data as values.
                        additionalProperties:
                          type: object
                          additionalProperties: false
                          properties:
                            match_content:
                              type: string
                              description: |
                                HTML content of a queried message that matches the narrow.  If the
                                narrow is a search narrow, `<span class="highlight">` elements
                                will be included, wrapping the matches for the search keywords.
                            match_subject:
                              type: string
                              description: |
                                HTML-escaped topic of a queried message that matches the narrow.  If the
                                narrow is a search narrow, `<span class="highlight">` elements
                                will be included wrapping the matches for the search keywords.
                          description: |
                            The ID of the message that matches the narrow.  No record will be returned
                            for queried messages that do not match the narrow.
                  - example:
                      {
                        "result": "success",
                        "msg": "",
                        "messages":
                          {
                            "31":
                              {
                                "match_content": '<p><a href="http://foo.com" target="_blank" title="http://foo.com">http://foo.com</a></p>',
                                "match_subject": "test_topic",
                              },
                          },
                      }
  /messages/{message_id}:
    get:
      operationId: get_raw_message
      tags: ["messages"]
      description: |
        Get the raw content of a message.

        `GET {{ api_url }}/v1/messages/{msg_id}`

        This is a rarely-used endpoint relevant for clients that primarily
        work with HTML-rendered messages but might need to occasionally fetch
        the message's raw markdown (e.g. for pre-filling a message-editing
        UI).
      parameters:
        - $ref: "#/components/parameters/MessageId"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      raw_content:
                        type: string
                        description: |
                          The raw content of the message.
                  - example:
                      {
                        "raw_content": "**Don't** forget your towel!",
                        "result": "success",
                        "msg": "",
                      }
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvalidMessageError"
    patch:
      operationId: update_message
      tags: ["messages"]
      description: |
        Edit/update the content or topic of a message.

        `PATCH {{ api_url }}/v1/messages/{msg_id}`

        `{msg_id}` in the above URL should be replaced with the ID of the
        message you wish you update.
      parameters:
        - $ref: "#/components/parameters/MessageId"
        - $ref: "#/components/parameters/Topic"
        - name: propagate_mode
          in: query
          description: |
            Which message(s) should be edited: just the one indicated in
            `message_id`, messages in the same topic that had been sent after this
            one, or all of them.
          schema:
            type: string
            enum:
              - change_one
              - change_later
              - change_all
            default: change_one
          example: change_all
        - name: send_notification_to_old_thread
          in: query
          description: |
            Whether to send breadcrumb message to the old thread to
            notify users where the messages were moved to.

            **Changes**: New in Zulip 3.0 (feature level 9).
          schema:
            type: boolean
            default: true
          example: true
        - name: send_notification_to_new_thread
          in: query
          description: |
            Whether to send a notification message to the new thread to
            notify users where the messages came from.

            **Changes**: New in Zulip 3.0 (feature level 9).
          schema:
            type: boolean
            default: true
          example: true
        - $ref: "#/components/parameters/OptionalContent"
        - $ref: "#/components/parameters/StreamIdInQuery"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/CodedError"
                  - properties:
                      msg:
                        enum:
                          - Your organization has turned off message editing
                          - You don't have permission to edit this message
                          - The time limit for editing this message has past
                          - Nothing to change
                          - Topic can't be empty
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "You don't have permission to edit this message",
                        "result": "error",
                      }
    delete:
      operationId: delete_message
      tags: ["messages"]
      description: |
        Permanently delete a message.

        `DELETE {{ api_url }}/v1/messages/{msg_id}`

        This API corresponds to the
        [delete a message completely][delete-completely] feature documented in
        the Zulip Help Center.
      parameters:
        - $ref: "#/components/parameters/MessageId"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/InvalidMessageError"
                  - allOf:
                      - $ref: "#/components/schemas/CodedError"
                      - example:
                          {
                            "code": "BAD_REQUEST",
                            "msg": "You don't have permission to delete this message",
                            "result": "error",
                          }
  /user_uploads:
    post:
      operationId: upload_file
      tags: ["messages"]
      description: |
        Upload a single file and get the corresponding URI.

        `POST {{ api_url }}/v1/user_uploads`

        Initially, only you will be able to access the link.  To share the
        uploaded file, you'll need to [send a message][send-message]
        containing the resulting link.  Users who can already access the link
        can reshare it with other users by sending additional Zulip messages
        containing the link.

        [uploaded-files]: /help/manage-your-uploaded-files
        [send-message]: /api/send-message
      requestBody:
        content:
          multipart/form-data:
            schema:
              properties:
                filename:
                  type: string
                  format: binary
                  example: /path/to/file
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      uri:
                        type: string
                        description: |
                          The URI of the uploaded file.
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "uri": "/user_uploads/1/4e/m2A3MSqFnWRLUf9SaPzQ0Up_/zulip.txt",
                      }
  /user_uploads/{realm_id_str}/{filename}:
    get:
      operationId: get_file_temporary_url
      tags: ["messages"]
      description: |
        Get a temporary URL for access to the file that doesn't require authentication.
      parameters:
        - name: realm_id_str
          in: path
          description: |
            The realm id.
          schema:
            type: integer
          example: 1
          required: true
        - name: filename
          in: path
          description: |
            Path to the URL.
          schema:
            type: string
          example: 4e/m2A3MSqFnWRLUf9SaPzQ0Up_/zulip.txt
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      url:
                        type: string
                        description: |
                          A temporary URL that can be used to access the uploaded file
                          without Zulip's normal API authentication.
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "url": "/user_uploads/temporary/322F32632F39765378464E4C63306D3961396F4970705A4D74424565432F7A756C69702E7478743A316A5053616A3A3938625F44393446466D37357254315F4F414C425A4553464F6A55",
                      }

  /users:
    get:
      operationId: get_users
      tags: ["users"]
      description: |
        Retrieve details on all users in the organization.  Optionally
        includes values of [custom profile field](/help/add-custom-profile-fields).

        `GET {{ api_url }}/v1/users`
      parameters:
        - $ref: "#/components/parameters/ClientGravatar"
        - $ref: "#/components/parameters/IncludeCustomProfileFields"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      members:
                        type: array
                        description: |
                          A list of `user` objects, each containing details about a user in the
                          organization.
                        items:
                          $ref: "#/components/schemas/User"
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "members":
                          [
                            {
                              "is_active": true,
                              "email": "AARON@zulip.com",
                              "is_admin": false,
                              "is_owner": false,
                              "avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1",
                              "bot_type": null,
                              "timezone": "",
                              "is_bot": false,
                              "user_id": 7,
                              "profile_data": {},
                              "is_guest": false,
                              "date_joined": "2019-10-20T07:50:53.728864+00:00",
                              "full_name": "aaron",
                            },
                            {
                              "date_joined": "2019-10-20T07:50:53.729659+00:00",
                              "full_name": "King Hamlet",
                              "is_guest": false,
                              "profile_data":
                                {
                                  "4": {"value": "vim"},
                                  "2":
                                    {
                                      "value": "I am:\n* The prince of Denmark\n* Nephew to the usurping Claudius",
                                      "rendered_value": "<p>I am:</p>\n<ul>\n<li>The prince of Denmark</li>\n<li>Nephew to the usurping Claudius</li>\n</ul>",
                                    },
                                  "5": {"value": "1900-1-1"},
                                  "7": {"value": "[11]"},
                                  "6": {"value": "https://blog.zulig.org"},
                                  "1":
                                    {
                                      "value": "+0-11-23-456-7890",
                                      "rendered_value": "<p>+0-11-23-456-7890</p>",
                                    },
                                  "8": {"value": "zulipbot"},
                                  "3":
                                    {
                                      "rendered_value": "<p>Dark chocolate</p>",
                                      "value": "Dark chocolate",
                                    },
                                },
                              "user_id": 10,
                              "is_bot": false,
                              "bot_type": null,
                              "timezone": "",
                              "is_admin": false,
                              "is_owner": false,
                              "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
                              "is_active": true,
                              "email": "hamlet@zulip.com",
                            },
                            {
                              "bot_owner_id": 11,
                              "is_guest": false,
                              "date_joined": "2019-10-20T12:52:17.862053+00:00",
                              "full_name": "Iago's Bot",
                              "email": "iago-bot@zulipdev.com",
                              "is_active": true,
                              "avatar_url": "https://secure.gravatar.com/avatar/7328586831cdbb1627649bd857b1ee8c?d=identicon&version=1",
                              "is_admin": false,
                              "is_owner": false,
                              "user_id": 23,
                              "bot_type": 1,
                              "timezone": "",
                              "is_bot": true,
                            },
                          ],
                      }
    post:
      operationId: create_user
      tags: ["users"]
      description: |
        {!api-admin-only.md!}

        Create a new user account via the API.

        `POST {{ api_url }}/v1/users`
      parameters:
        - name: email
          in: query
          description: |
            The email address of the new user.
          schema:
            type: string
          example: username@example.com
          required: true
        - name: password
          in: query
          description: |
            The password of the new user.
          schema:
            type: string
          example: abcd1234
          required: true
        - name: full_name
          in: query
          description: |
            The full name of the new user.
          schema:
            type: string
          example: New User
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "msg": "Email 'newbie@zulip.com' already in use",
                        "result": "error",
                      }

  /users/{user_id}/reactivate:
    post:
      operationId: reactivate_user
      tags: ["users"]
      description: |
        {!api-admin-only.md!}

        [Reactivates a
        user](https://zulip.com/help/deactivate-or-reactivate-a-user)
        given their user ID.

        `POST {{ api_url }}/v1/users/{user_id}/reactivate`
      parameters:
        - $ref: "#/components/parameters/UserId"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"msg": "", "result": "success"}

  /users/{email}/presence:
    get:
      operationId: get_user_presence
      tags: ["users"]
      description: |
        Get the presence status for a specific user.

        This endpoint is most useful for embedding data about a user's
        presence status in other sites (E.g. an employee directory).  Full
        Zulip clients like mobile/desktop apps will want to use the main
        presence endpoint, which returns data for all active users in the
        organization, instead.

        `GET {{ api_url }}/v1/users/{email}/presence`

        See
        [Zulip's developer documentation](https://zulip.readthedocs.io/en/latest/subsystems/presence.html)
        for details on the data model for presence in Zulip.
      parameters:
        - name: email
          in: path
          description: |
            The email address of the user whose presence you want to fetch.
          schema:
            type: string
          example: iago@zulip.com
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      presence:
                        type: object
                        description: |
                          An object containing the presence details for every client the user has
                          logged into.
                        additionalProperties:
                          type: object
                          additionalProperties: false
                          properties:
                            timestamp:
                              type: integer
                              description: |
                                when this update was received; if the timestamp
                                is more than a few minutes in the past, the user is offline.
                            status:
                              type: string
                              description: |
                                either `active` or `idle`: whether the user had
                                recently interacted with Zulip at the time in the timestamp
                                (this distinguishes orange vs. green dots in the Zulip web
                                UI; orange/idle means we don't know whether the user is
                                actually at their computer or just left the Zulip app open
                                on their desktop).
                          description: |
                            `{client_name}` or `aggregated`: the keys for these objects are
                            the names of the different clients where this user is logged in,
                            like `website`, `ZulipDesktop`, `ZulipTerminal`, or
                            `ZulipMobile`. There is also an `aggregated` key, which matches
                            the contents of the object that has been updated most
                            recently. For most applications, you'll just want to look at the
                            `aggregated` key.
                  - example:
                      {
                        "presence":
                          {
                            "website":
                              {"timestamp": 1532697622, "status": "active"},
                            "ZulipMobile":
                              {"timestamp": 1522687421, "status": "active"},
                            "aggregated":
                              {"timestamp": 1532697622, "status": "active"},
                          },
                        "result": "success",
                        "msg": "",
                      }
  /users/me:
    get:
      operationId: get_own_user
      tags: ["users"]
      description: |
        Get basic data about the user/bot that requests this endpoint.

        `GET {{ api_url }}/v1/users/me`
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      avatar_url:
                        type: string
                        description: |
                          URL for the user's avatar.

                          **Changes**: New in Zulip 2.1.0.
                        example: "x"
                      avatar_version:
                        type: integer
                        description: |
                          Version for the the user's avatar.  Used for cache-busting requests
                          for the user's avatar.  Clients generally shouldn't need to use this;
                          most avatar URLs sent by Zulip will already end with `?v={avatar_version}`.

                          **Changes**: New in Zulip 3.0 (feature level 10). Previous
                          versions do not return this field.
                        example: 1
                      email:
                        type: string
                        description: |
                          Email of the requesting user.
                        example: "iago@zulip.com"
                      full_name:
                        type: string
                        description: |
                          Full name of the requesting user.
                        example: "Iago"
                      is_admin:
                        type: boolean
                        description: |
                          A boolean indicating if the requesting user is an admin.
                        example: true
                      is_owner:
                        type: boolean
                        description: |
                          A boolean indicating if the requesting user is
                          an organization owner.

                          **Changes**: New in Zulip 3.0 (feature level 8).
                        example: false
                      is_guest:
                        type: boolean
                        description: |
                          A boolean indicating if the requesting user is a guest.

                          **Changes**: New in Zulip 3.0 (feature level 10). Previous
                          versions do not return this field.
                        example: false
                      is_bot:
                        type: boolean
                        description: |
                          A boolean indicating if the requesting user is a bot.
                        example: false
                      is_active:
                        type: boolean
                        description: |
                          A boolean specifying whether the user account has been deactivated.

                          **Changes**: New in Zulip 3.0 (feature level 10). Previous
                          versions do not return this field.
                        example: true
                      timezone:
                        type: string
                        description: |
                          The time zone of the user.

                          **Changes**: New in Zulip 3.0 (feature level 10). Previous
                          versions do not return this field.
                        example: ""
                      date_joined:
                        type: string
                        description: |
                          The time the user account was created.

                          **Changes**: New in Zulip 3.0 (feature level 10). Previous
                          versions do not return this field.
                        example: "2019-10-20T07:50:53.728864+00:00"
                      max_message_id:
                        type: integer
                        deprecated: true
                        description: |
                          The integer ID of the last message received by your account.

                          **Deprecated**.  We plan to remove this in favor of recommending
                          using `GET /messages` with `anchor="newest"`.
                        example: 30
                      user_id:
                        type: integer
                        description: |
                          The user's ID.
                        example: 1
                      delivery_email:
                        type: string
                        description: |
                          The user's real email address.  This field is present only if
                          [email address visibility](/help/restrict-visibility-of-email-addresses) is
                          limited and you are an administrator with access to real email addresses
                          under the configured policy.
                      profile_data:
                        $ref: "#/components/schemas/profile_data"
                  - example:
                      {
                        "avatar_url": "https://secure.gravatar.com/avatar/af4f06322c177ef4e1e9b2c424986b54?d=identicon&version=1",
                        "avatar_version": 1,
                        "email": "iago@zulip.com",
                        "full_name": "Iago",
                        "is_admin": true,
                        "is_owner": false,
                        "is_guest": false,
                        "is_bot": false,
                        "is_active": true,
                        "timezone": "",
                        "date_joined": "2019-10-20T07:50:53.728864+00:00",
                        "max_message_id": 30,
                        "msg": "",
                        "result": "success",
                        "user_id": 5,
                        "profile_data":
                          {
                            "5": {"value": "2000-1-1"},
                            "4": {"value": "emacs"},
                            "7": {"value": "[10]"},
                            "1":
                              {
                                "value": "+1-234-567-8901",
                                "rendered_value": "<p>+1-234-567-8901</p>",
                              },
                            "2":
                              {
                                "rendered_value": "<p>Betrayer of Othello.</p>",
                                "value": "Betrayer of Othello.",
                              },
                            "8": {"value": "zulip"},
                            "3":
                              {
                                "value": "Apples",
                                "rendered_value": "<p>Apples</p>",
                              },
                            "6":
                              {
                                "value": "https://zulip.readthedocs.io/en/latest/",
                              },
                          },
                      }
    delete:
      operationId: deactivate_my_account
      tags: ["users"]
      description: |
        Delete the requesting user from the realm.
      responses:
        "200":
          description: Bad Request
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"msg": "", "result": "success"}
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "msg": "Cannot deactivate the only organization administrator",
                        "result": "error",
                      }
  /users/me/{stream_id}/topics:
    get:
      operationId: get_stream_topics
      tags: ["streams"]
      description: |
        Get all the topics in a specific stream

        `GET {{ api_url }}/v1/users/me/{stream_id}/topics`
      parameters:
        - $ref: "#/components/parameters/StreamIdInPath"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      topics:
                        type: array
                        description: |
                          An array of `topic` objects.
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            max_id:
                              description: |
                                The message ID of the last message sent to this topic.
                              type: integer
                            name:
                              description: |
                                The name of the topic.
                              type: string
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "topics":
                          [
                            {"max_id": 26, "name": "Denmark3"},
                            {"max_id": 23, "name": "Denmark1"},
                            {"max_id": 6, "name": "Denmark2"},
                          ],
                      }
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "Invalid stream id",
                        "result": "error",
                      }
  /users/me/subscriptions:
    get:
      operationId: get_subscriptions
      tags: ["streams"]
      description: |
        Get all streams that the user is subscribed to.

        `GET {{ api_url }}/v1/users/me/subscriptions`
      # operationId can be used to record which view function
      # corresponds to an endpoint.  TODO: Add these for more
      # endpoints, and perhaps use this to provide links to implementations.
      parameters:
        - $ref: "#/components/parameters/IncludeSubscribers"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  # TODO: Is this the best way to declare required elements in 200 responses?
                  - required:
                      - subscriptions
                  - properties:
                      subscriptions:
                        type: array
                        description: |
                          A list of dictionaries where each dictionary contains
                          information about one of the subscribed streams.
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            stream_id:
                              type: integer
                              description: |
                                The unique ID of a stream.
                            name:
                              type: string
                              description: |
                                The name of a stream.
                            description:
                              type: string
                              description: |
                                The short description of a stream in text/markdown format,
                                intended to be used to prepopulate UI for editing a stream's
                                description.
                            rendered_description:
                              type: string
                              description: |
                                A short description of a stream rendered as HTML, intended to
                                be used when displaying the stream description in a UI.

                                One should use the standard Zulip rendered_markdown CSS when
                                displaying this content so that emoji, LaTeX, and other syntax
                                work correctly.  And any client-side security logic for
                                user-generated message content should be applied when displaying
                                this HTML as though it were the body of a Zulip message.
                            invite_only:
                              type: boolean
                              description: |
                                Specifies whether the stream is private or not.
                                Only people who have been invited can access a private stream.
                            # TODO: This subscribers item should probably be declared optional more
                            # explicitly in the OpenAPI format?
                            subscribers:
                              type: array
                              items:
                                type: integer
                              description: |
                                A list of user IDs of users who are also subscribed
                                to a given stream. Included only if `include_subscribers` is `true`.
                            desktop_notifications:
                              type: boolean
                              nullable: true
                              description: |
                                A boolean specifying whether desktop notifications
                                are enabled for the given stream.

                                A null value means the value of this setting
                                should be inherited from the user-level default
                                setting, enable_stream_desktop_notifications, for
                                this stream.
                            email_notifications:
                              type: boolean
                              nullable: true
                              description: |
                                A boolean specifying whether email notifications
                                are enabled for the given stream.

                                A null value means the value of this setting
                                should be inherited from the user-level default
                                setting, enable_stream_email_notifications, for
                                this stream.
                            wildcard_mentions_notify:
                              type: boolean
                              nullable: true
                              description: |
                                A boolean specifying whether wildcard mentions
                                trigger notifications as though they were personal
                                mentions in this stream.

                                A null value means the value of this setting
                                should be inherited from the user-level default
                                setting, wildcard_mentions_notify, for
                                this stream.
                            push_notifications:
                              type: boolean
                              nullable: true
                              description: |
                                A boolean specifying whether push notifications
                                are enabled for the given stream.

                                A null value means the value of this setting
                                should be inherited from the user-level default
                                setting, enable_stream_push_notifications, for
                                this stream.
                            audible_notifications:
                              type: boolean
                              nullable: true
                              description: |
                                A boolean specifying whether audible notifications
                                are enabled for the given stream.

                                A null value means the value of this setting
                                should be inherited from the user-level default
                                setting, enable_stream_audible_notifications, for
                                this stream.
                            pin_to_top:
                              type: boolean
                              description: |
                                A boolean specifying whether the given stream has been pinned
                                to the top.
                            email_address:
                              type: string
                              description: |
                                Email address of the given stream, used for
                                [sending emails to the stream](/help/message-a-stream-by-email).
                            is_muted:
                              type: boolean
                              description: |
                                Whether the user has muted the stream. Muted streams do
                                not count towards your total unread count and do not show up in
                                `All messages` view (previously known as `Home` view).

                                **Changes**: Prior to Zulip 2.1, this feature was
                                represented by the more confusingly named `in_home_view` (with the
                                opposite value, `in_home_view=!is_muted`).
                            in_home_view:
                              type: boolean
                              deprecated: true
                              description: |
                                Legacy property for if the given stream is muted, with inverted meeting.

                                **Deprecated**; clients should use is_muted where available.
                            is_announcement_only:
                              type: boolean
                              deprecated: true
                              description: |
                                Whether only organization administrators can post to the stream.

                                **Changes**: Deprecated in Zulip 3.0 (feature level 1), use
                                `stream_post_policy` instead.
                            is_web_public:
                              type: boolean
                              description: |
                                Whether the stream has been configured to allow unauthenticated
                                access to its message history from the web.
                            color:
                              type: string
                              description: |
                                The user's personal color for the stream.
                            stream_post_policy:
                              type: integer
                              description: |
                                Policy for which users can post messages to the stream.

                                * 1 => Any user can post.
                                * 2 => Only administrators can post.
                                * 3 => Only new members can post.

                                **Changes**: New in Zulip 3.0, replacing the previous
                                `is_announcement_only` boolean.
                            message_retention_days:
                              type: integer
                              nullable: true
                              description: |
                                Number of days that messages sent to this stream will be stored
                                before being automatically deleted by the [message retention
                                policy](/help/message-retention-policy).  There are two special values:

                                * `null`, the default, means the stream will inherit the organization
                                  level setting.
                                * `-1` encodes retaining messages in this stream forever.

                                **Changes**: New in Zulip 3.0 (feature level 17).
                            history_public_to_subscribers:
                              type: boolean
                              description: |
                                Whether the history of the stream is public to its subscribers.

                                Currently always true for public streams (i.e. invite_only=False implies
                                history_public_to_subscribers=True), but clients should not make that
                                assumption, as we may change that behavior in the future.
                            first_message_id:
                              type: integer
                              description: |
                                The id of the first message in the stream.

                                Intended to help clients determine whether they need to display
                                UI like the "more topics" widget that would suggest the stream
                                has older history that can be accessed.

                                Null is used for streams with no message history.
                            stream_weekly_traffic:
                              type: integer
                              nullable: true
                              description: |
                                The average number of messages sent to the stream in recent weeks,
                                rounded to the nearest integer.

                                Null means the stream was recently created and there is
                                insufficient data to estimate the average traffic.
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "subscriptions":
                          [
                            {
                              "audible_notifications": true,
                              "color": "#e79ab5",
                              "description": "A Scandinavian country",
                              "desktop_notifications": true,
                              "email_address": "Denmark+187b4125ed36d6af8b5d03ef4f65c0cf@zulipdev.com:9981",
                              "is_muted": false,
                              "invite_only": false,
                              "name": "Denmark",
                              "pin_to_top": false,
                              "push_notifications": false,
                              "stream_id": 1,
                              "subscribers": [7, 10, 11, 12, 14],
                            },
                            {
                              "audible_notifications": true,
                              "color": "#e79ab5",
                              "description": "Located in the United Kingdom",
                              "desktop_notifications": true,
                              "email_address": "Scotland+f5786390183e60a1ccb18374f9d05649@zulipdev.com:9981",
                              "is_muted": false,
                              "invite_only": false,
                              "name": "Scotland",
                              "pin_to_top": false,
                              "push_notifications": false,
                              "stream_id": 3,
                              "subscribers": [7, 11, 12, 14],
                            },
                          ],
                      }
    post:
      operationId: subscribe
      tags: ["streams"]
      description: |
        Subscribe one or more users to one or more streams.

        `POST {{ api_url }}/v1/users/me/subscriptions`

        If any of the specified streams do not exist, they are automatically
        created.  The initial [stream settings](/api/update-stream) will be determined
        by the optional parameters like `invite_only` detailed below.
      parameters:
        - name: subscriptions
          in: query
          description: |
            A list of dictionaries containing the the key `name` and value
            specifying the name of the stream to subscribe. If the stream does not
            exist a new stream is created. The description of the stream created can
            be specified by setting the dictionary key `description` with an
            appropriate value.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example: [{"name": "Verona", "description": "Italian City"}]
          required: true
        - $ref: "#/components/parameters/Principals"
        - name: authorization_errors_fatal
          in: query
          description: |
            A boolean specifying whether authorization errors (such as when the
            requesting user is not authorized to access a private stream) should be
            considered fatal or not. When `True`, an authorization error is reported
            as such. When set to `False`, the response will be a 200 and any streams
            where the request encountered an authorization error will be listed
            in the `unauthorized` key.
          schema:
            type: boolean
            default: true
          example: false
        - name: announce
          in: query
          description: |
            If one of the streams specified did not exist previously and is thus craeted
            by this call, this determines whether [notification bot](/help/configure-notification-bot)
            will send an announcement about the new stream's creation.
          schema:
            type: boolean
            default: false
          example: true
        - name: invite_only
          in: query
          description: |
            As described above, this endpoint will create a new stream if passed
            a stream name that doesn't already exist.  This parameters and the ones
            that follow are used to request an initial configuration of a created
            stream; they are ignored for streams that already exist.

            This parameter determines whether any newly created streams will be
            private streams.
          schema:
            type: boolean
            default: false
          example: true
        - $ref: "#/components/parameters/HistoryPublicToSubscribers"
        - $ref: "#/components/parameters/StreamPostPolicy"
        - $ref: "#/components/parameters/MessageRetentionDays"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                oneOf:
                  - allOf:
                      - $ref: "#/components/schemas/AddSubscriptionsResponse"
                      - example:
                          {
                            "already_subscribed": {},
                            "msg": "",
                            "result": "success",
                            "subscribed": {"iago@zulip.com": ["new stream"]},
                          }
                  - allOf:
                      - $ref: "#/components/schemas/AddSubscriptionsResponse"
                      - example:
                          {
                            "already_subscribed":
                              {"newbie@zulip.com": ["new stream"]},
                            "msg": "",
                            "result": "success",
                            "subscribed": {},
                          }
        "400":
          description: Success.
          content:
            application/json:
              schema:
                oneOf:
                  - allOf:
                      - $ref: "#/components/schemas/AddSubscriptionsResponse"
                      - example:
                          {
                            "msg": "Unable to access stream (private_stream).",
                            "result": "error",
                          }
                  - allOf:
                      - $ref: "#/components/schemas/AddSubscriptionsResponse"
                      - example:
                          {
                            "already_subscribed": {},
                            "msg": "",
                            "result": "success",
                            "subscribed": {},
                            "unauthorized": ["private_stream"],
                          }
    patch:
      operationId: update_subscriptions
      tags: ["streams"]
      description: |
        Update which streams you are are subscribed to.
      parameters:
        - name: delete
          in: query
          description: |
            A list of stream names to unsubscribe from.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              example: ["Verona", "Denmark"]
          required: false
        - name: add
          in: query
          description: |
            A list of objects describing which streams to subscribe to, optionally
            including per-user subscription parameters (e.g. color) and if the
            stream is to be created, its description.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  additionalProperties: false
                  properties:
                    name:
                      type: string
                    color:
                      type: string
                    description:
                      type: string
              example:
                [
                  {"name": "Verona"},
                  {
                    "name": "Denmark",
                    "color": "#e79ab5",
                    "description": "A Scandinavian country",
                  },
                ]
          required: false
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - required:
                      - subscribed
                      - already_subscribed
                      - removed
                  - properties:
                      subscribed:
                        type: object
                        description: |
                          A dictionary where the key is the email
                          address of the user/bot and the value is a
                          list of the names of the streams that were
                          subscribed to as a result of the query.
                        additionalProperties:
                          description: |
                            `{email_id}`: A list of the names of streams that
                            the user was subscribed to as a result of the query.
                          type: array
                          items:
                            type: string
                      already_subscribed:
                        type: object
                        description: |
                          A dictionary where the key is the email
                          address of the user/bot and the value is a
                          list of the names of the streams that the
                          user/bot is already subscribed to.
                        additionalProperties:
                          description: |
                            `{email_id}`: A list of the names of streams that
                            the user was already subscribed to.
                          type: array
                          items:
                            type: string
                      not_removed:
                        type: array
                        items:
                          type: string
                        description: |
                          A list of the names of streams that the user
                          is already unsubscribed from, and hence
                          doesn't need to be unsubscribed.
                      removed:
                        type: array
                        items:
                          type: string
                        description: |
                          A list of the names of streams which were unsubscribed
                          from as a result of the query.
                  - example:
                      {
                        "msg": "",
                        "subscribed": {},
                        "already_subscribed": {"iago@zulip.com": ["Verona"]},
                        "not_removed": [],
                        "removed": ["new stream"],
                        "result": "success",
                      }
    delete:
      operationId: unsubscribe
      tags: ["streams"]
      description: |
        Unsubscribe yourself or other users from one or more streams.

        `DELETE {{ api_url }}/v1/users/me/subscriptions`
      parameters:
        - name: subscriptions
          in: query
          description: |
            A list of stream names to unsubscribe from. This parameter is called
            `streams` in our Python API.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              example: ["Verona", "Denmark"]
          required: true
        - $ref: "#/components/parameters/Principals"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      not_removed:
                        type: array
                        items:
                          type: string
                        description: |
                          A list of the names of streams that the user is already unsubscribed
                          from, and hence doesn't need to be unsubscribed.
                      removed:
                        type: array
                        items:
                          type: string
                        description: |
                          A list of the names of streams which were unsubscribed from as a result
                          of the query.
                  - example:
                      {
                        "msg": "",
                        "not_removed": [],
                        "removed": ["new stream"],
                        "result": "success",
                      }
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NonExistingStreamError"
  /users/{user_id}/subscriptions/{stream_id}:
    get:
      operationId: get_subscription_status
      tags: ["streams"]
      description: |
        Check whether a user is subscribed to a stream.

        `GET {{ api_url }}/v1/users/{user_id}/subscriptions/{stream_id}`

        **Changes**: New in Zulip 3.0 (feature level 11).
      parameters:
        - $ref: "#/components/parameters/UserId"
          example: 7
        - $ref: "#/components/parameters/StreamIdInPath"
          example: 1
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      is_subscribed:
                        type: boolean
                        description: |
                          Whether the user is subscribed to the stream.
                  - example:
                      {"msg": "", "result": "success", "is_subscribed": false}
  /users/me/subscriptions/muted_topics:
    patch:
      operationId: mute_topic
      tags: ["streams"]
      description: |
        This endpoint mutes/unmutes a topic within a stream that the current
        user is subscribed to.  Muted topics are displayed faded in the Zulip
        UI, and are not included in the user's unread count totals.

        `PATCH {{ api_url }}/v1/users/me/subscriptions/muted_topics`

      parameters:
        - $ref: "#/components/parameters/Stream"
          required: false
        - $ref: "#/components/parameters/StreamIdInQuery"
          required: false
        - name: topic
          in: query
          description: |
            The topic to (un)mute. Note that the request will succeed regardless of
            whether any messages have been sent to the specified topic.
          schema:
            type: string
          example: dinner
          required: true
        - name: op
          in: query
          description: |
            Whether to mute (`add`) or unmute (`remove`) the provided topic.
          schema:
            type: string
            enum:
              - add
              - remove
          example: add
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                oneOf:
                  - allOf:
                      - $ref: "#/components/schemas/JsonError"
                      - example:
                          {"msg": "Topic already muted", "result": "error"}
                  - allOf:
                      - $ref: "#/components/schemas/JsonError"
                      - example:
                          {"msg": "Topic is not muted", "result": "error"}
  /realm/emoji/{emoji_name}:
    post:
      operationId: upload_custom_emoji
      tags: ["server_and_organizations"]
      description: |
        This endpoint is used to upload a custom emoji for use in the user's
        organization.  Access to this endpoint depends on the
        [organization's configuration](https://zulip.com/help/only-allow-admins-to-add-emoji).

        `POST {{ api_url }}/v1/realm/emoji/{emoji_name}`
      parameters:
        - name: emoji_name
          required: true
          in: path
          description: |
            The name that should be associated with the uploaded emoji image/gif.
          schema:
            type: string
      requestBody:
        content:
          multipart/form-data:
            schema:
              properties:
                filename:
                  type: string
                  format: binary
                  example: /path/to/img.png
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"

  /realm/emoji:
    get:
      operationId: get_custom_emoji
      tags: ["server_and_organizations"]
      description: |
        Get all the custom emoji in the user's organization.

        `GET {{ api_url }}/v1/realm/emoji`
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      emoji:
                        type: object
                        description: |
                          An object that contains `emoji` objects, each identified with their
                          emoji ID as the key.
                        additionalProperties:
                          type: object
                          additionalProperties: false
                          description: |
                            `{emoji_id}`: Object containing details about the emoji with
                             the specified ID. It has the following properties:
                          properties:
                            id:
                              type: string
                              description: |
                                The ID for this emoji, same as the object's key.
                            name:
                              type: string
                              description: |
                                The user-friendly name for this emoji. Users in the organization
                                can use this emoji by writing this name between colons (`:name  :`).
                            source_url:
                              type: string
                              description: |
                                The path relative to the organization's URL where the
                                emoji's image can be found.
                            deactivated:
                              type: boolean
                              description: |
                                Whether the emoji has been deactivated or not.
                            author_id:
                              type: integer
                              nullable: true
                              description: |
                                The user ID of the user who uploaded the custom emoji.
                                Will be null if the uploader is unknown.

                                **Changes**: New in Zulip 3.0 (feature level 7).  Previously
                                was accessible via and `author` object with an `id` field.
                  - example:
                      {
                        "result": "success",
                        "msg": "",
                        "emoji":
                          {
                            "1":
                              {
                                "id": "1",
                                "name": "green_tick",
                                "source_url": "/user_avatars/1/emoji/images/1.png",
                                "deactivated": false,
                                "author_id": 5,
                              },
                          },
                      }
  /users/me/subscriptions/properties:
    post:
      operationId: update_subscription_settings
      tags: ["streams"]
      description: |
        This endpoint is used to update the user's personal settings for the
        streams they are subscribed to, including muting, color, pinning, and
        per-stream notification settings.

        `POST {{ api_url }}/v1/users/me/subscriptions/properties`
      parameters:
        - name: subscription_data
          in: query
          description: |
            A list of objects that describe the changes that should be applied in
            each subscription. Each object represents a subscription, and must have
            a `stream_id` key that identifies the stream, as well as the `property`
            being modified and its new `value`.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example:
                [
                  {"stream_id": 1, "property": "pin_to_top", "value": true},
                  {"stream_id": 3, "property": "color", "value": "#f00f00"},
                ]
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      subscription_data:
                        type: array
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            property:
                              type: string
                              description: |
                                The property to be changed. It is one of:
                                    *`color`: The hex value of the user's personal display color for the stream.

                                    *`is_muted`: Whether the stream is [muted](/help/mute-a-stream).

                                    **Changes**: Prior to Zulip 2.1, this feature was
                                    represented by the more confusingly named `in_home_view` (with the
                                    opposite value, `in_home_view=!is_muted`); for
                                    backwards-compatibility, modern Zulip still accepts that value.

                                    *`pin_to_top`: Whether to pin the stream at the top of the stream list.

                                    *`desktop_notifications`: Whether to show desktop notifications for all
                                    messages sent to the stream.

                                    *`audible_notifications`: Whether to play a sound notification for all
                                    messages sent to the stream.

                                    *`push_notifications`: Whether to trigger a mobile push notification for
                                    all messages sent to the stream.

                                    *`email_notifications`: Whether to trigger an email notification for all
                                    messages sent to the stream.

                                    *`in_home_view`: Whether to mute the stream (Legacy property)

                                    *`wildcard_mentions_notify`: whether wildcard mentions trigger notifications
                                    as though they were personal mentions in this stream.

                                    A null value means the value of this setting
                                    should be inherited from the user-level default
                                    setting, wildcard_mentions_notify, for
                                    this stream.
                              enum:
                                - color
                                - push_notifications
                                - is_muted
                                - pin_to_top
                                - desktop_notifications
                                - audible_notifications
                                - push_notifications
                                - email_notifications
                                - in_home_view
                                - wildcard_mentions_notify
                            value:
                              description: |
                                The desired value of the property
                              oneOf:
                                - type: boolean
                                - type: string
                            stream_id:
                              description: |
                                The desired value of the property
                              type: integer
                        description: |
                          The same `subscription_data` array sent by the client for the request.
                  - example:
                      {
                        "subscription_data":
                          [
                            {
                              "property": "pin_to_top",
                              "value": true,
                              "stream_id": 1,
                            },
                            {
                              "property": "color",
                              "value": "#f00f00",
                              "stream_id": 3,
                            },
                          ],
                        "result": "success",
                        "msg": "",
                      }
  /users/{user_id}:
    get:
      operationId: get_user
      tags: ["users"]
      description: |
        Fetch details for a single user in the organization.

        `GET {{ api_url }}/v1/users/{user_id}`

        You can also fetch details on [all users in the organization](/api/get-users).

        *This endpoint is new in Zulip Server 3.0 (feature level 1).*
      parameters:
        - $ref: "#/components/parameters/UserId"
        - $ref: "#/components/parameters/ClientGravatar"
        - $ref: "#/components/parameters/IncludeCustomProfileFields"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      user:
                        $ref: "#/components/schemas/User"
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "user":
                          {
                            "date_joined": "2019-10-20T07:50:53.729659+00:00",
                            "full_name": "King Hamlet",
                            "is_guest": false,
                            "profile_data":
                              {
                                "4": {"value": "vim"},
                                "2":
                                  {
                                    "value": "I am:\n* The prince of Denmark\n* Nephew to the usurping Claudius",
                                    "rendered_value": "<p>I am:</p>\n<ul>\n<li>The prince of Denmark</li>\n<li>Nephew to the usurping Claudius</li>\n</ul>",
                                  },
                                "5": {"value": "1900-1-1"},
                                "7": {"value": "[11]"},
                                "6": {"value": "https://blog.zulig.org"},
                                "1":
                                  {
                                    "value": "+0-11-23-456-7890",
                                    "rendered_value": "<p>+0-11-23-456-7890</p>",
                                  },
                                "8": {"value": "zulipbot"},
                                "3":
                                  {
                                    "rendered_value": "<p>Dark chocolate</p>",
                                    "value": "Dark chocolate",
                                  },
                              },
                            "user_id": 10,
                            "is_bot": false,
                            "bot_type": null,
                            "timezone": "",
                            "is_admin": false,
                            "is_owner": false,
                            "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1",
                            "is_active": true,
                            "email": "hamlet@zulip.com",
                          },
                      }
    patch:
      operationId: update_user
      tags: ["users"]
      description: |
        {!api-admin-only.md!}

        Administrative endpoint to update the details of another user in the organization.

        `PATCH {{ api_url }}/v1/users/{user_id}`

        Supports everything an administrator can do to edit details of another
        user's account, including editing full name,
        [role](/help/roles-and-permissions), and [custom profile
        fields](/help/add-custom-profile-fields).
      parameters:
        - $ref: "#/components/parameters/UserId"
        - name: full_name
          in: query
          description: |
            The user's full name.
          content:
            application/json:
              schema:
                type: string
              example: NewName
          required: false
        - name: role
          in: query
          description: |
            New [role](/help/roles-and-permissions) for the user.  Roles are encoded as:

            * Organization owner: 100
            * Organization administrator: 200
            * Member: 400
            * Guest: 600

            Only organization owners can add or remove the owner role.

            The owner role cannot be removed from the only organization owner.

            **Changes**: New in Zulip 3.0 (feature level 8), replacing the previous
            pair of `is_admin` and `is_guest` boolean parameters.
          schema:
            type: integer
          example: 400
          required: false
        - name: profile_data
          in: query
          description: |
            A dictionary containing the to be updated custom profile field data for the user.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example:
                [{"id": 4, "value": "vim"}, {"id": 5, "value": "1909-04-05"}]
          required: false

      responses:
        "200":
          $ref: "#/components/responses/SimpleSuccess"

        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/CodedError"
                  - example:
                      {
                        "result": "error",
                        "msg": "Guests cannot be organization administrators",
                        "code": "BAD_REQUEST",
                      }

    delete:
      operationId: deactivate_user
      tags: ["users"]
      description: |
        {!api-admin-only.md!}

        [Deactivates a
        user](https://zulip.com/help/deactivate-or-reactivate-a-user)
        given their user ID.

        `DELETE {{ api_url }}/v1/users/{user_id}`
      parameters:
        - $ref: "#/components/parameters/UserId"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"msg": "", "result": "success"}
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "msg": "Cannot deactivate the only organization administrator",
                        "result": "error",
                      }
  /realm/filters:
    get:
      operationId: get_linkifiers
      tags: ["server_and_organizations"]
      description: |
        List all of an organization's configured
        [linkifiers](/help/add-a-custom-linkification-filter), regular
        expression patterns that are automatically linkified when they appear
        in messages and topics.

        `GET {{ api_url }}/v1/realm/filters`
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      filters:
                        type: array
                        items:
                          type: array
                          items:
                            oneOf:
                              - type: string
                              - type: integer
                        description: |
                          An array of tuples, each representing one of
                          the linkifiers set up in the
                          organization. Each of these tuples contain the
                          pattern, the formatted URL and the filter's
                          ID, in that order. See the [Create
                          linkifiers](/api/add-linkifier) article for
                          details on what each field means.
                  - example:
                      {
                        "msg": "",
                        "filters":
                          [
                            [
                              "#(?P<id>[0-9]+)",
                              "https://github.com/zulip/zulip/issues/%(id)s",
                              1,
                            ],
                          ],
                        "result": "success",
                      }
    post:
      operationId: add_linkifier
      tags: ["server_and_organizations"]
      description: |
        Configure [linkifiers](/help/add-a-custom-linkification-filter),
        regular expression patterns that are automatically linkified when they
        appear in messages and topics.

        `POST {{ api_url }}/v1/realm/filters`
      parameters:
        - name: pattern
          in: query
          description: |
            The [Python regular
            expression](https://docs.python.org/3/howto/regex.html) that should
            trigger the linkifier.
          schema:
            type: string
          example: "#(?P<id>[0-9]+)"
          required: true
        - name: url_format_string
          in: query
          description: |
            The URL used for the link. If you used named groups for the `pattern`,
            you can insert their content here with
            `%(name_of_the_capturing_group)s`.
          schema:
            type: string
          example: https://github.com/zulip/zulip/issues/%(id)s
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      id:
                        type: integer
                        description: |
                          The numeric ID assigned to this filter.
                  - example: {"id": 42, "result": "success", "msg": ""}
  /realm/filters/{filter_id}:
    delete:
      operationId: remove_linkifier
      tags: ["server_and_organizations"]
      description: |
        Remove [linkifiers](/help/add-a-custom-linkification-filter), regular
        expression patterns that are automatically linkified when they appear
        in messages and topics.

        `DELETE {{ api_url }}/v1/realm/filters/{filter_id}`
      parameters:
        - name: filter_id
          in: path
          description: |
            The ID of the filter that you want to remove.
          schema:
            type: integer
          example: 42
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"
  /register:
    post:
      operationId: register_queue
      tags: ["real_time_events"]
      description: |
        This powerful endpoint can be used to register a Zulip "event queue"
        (subscribed to certain types of "events", or updates to the messages and
        other Zulip data the current user has access to), as well as to fetch
        the current state of that data.
      parameters:
        - name: apply_markdown
          in: query
          description: |
            Set to `true` if you would like the content to be rendered in HTML
            format (otherwise the API will return the raw text that the user
            entered)
          schema:
            type: boolean
            default: false
          example: true
        - $ref: "#/components/parameters/ClientGravatar"
        - name: slim_presence
          in: query
          description: |
            Setting this to `true` will make presence dictionaries be keyed by
            user_id instead of email.

            **Changes**: New in Zulip 3.0 (Unstable with no feature level yet).
          schema:
            type: boolean
            default: false
          example: true
        - $ref: "#/components/parameters/Event_types"
        - name: all_public_streams
          in: query
          description: |
            Set to `True` if you would like to receive events that occur within all
            public streams.
          schema:
            type: boolean
            default: false
          example: true
        - $ref: "#/components/parameters/IncludeSubscribers"
        - name: client_capabilities
          in: query
          description: |
            Dictionary containing details on features the client supports that are
            relevant to the format of responses sent by the server.

            * `notification_settings_null`: Boolean for whether the
              client can handle the current API with null values for
              stream-level notification settings (which means the stream
              is not customized and should inherit the user's global
              notification settings for stream messages).  New in Zulip
              2.1.0; in earlier Zulip releases, stream-level
              notification settings were simple booleans.

            * `bulk_message_deletion`: Boolean for whether the client's
               handler for the `delete_message` event type has been
               updated to process the new bulk format (with a
               `message_ids`, rather than a singleton `message_id`).
               Otherwise, the server will send `delete_message` events
               in a loop.  New in Zulip 3.0 (feature level 13).  This
               capability is for backwards-compatibility; it will be
               required in a future server release.

            * `user_avatar_url_field_optional`: Boolean for whether the
               client required avatar URLs for all users, or supports
               using `GET /avatar/{user_id}` to access user avatars.  If the
               client has this capability, the server may skip sending a
               `avatar_url` field in the `realm_user` at its sole discretion
               to optimize network performance.  This is an important optimization
               in organizations with 10,000s of users.
               New in Zulip 3.0 (feature level 18).
          content:
            application/json:
              schema:
                type: object
              example: {"notification_settings_null": true}
        - name: fetch_event_types
          in: query
          description: |
            Same as the `event_types` parameter except that the values in
            `fetch_event_types` are used to fetch initial data. If
            `fetch_event_types` is not provided, `event_types` is used and if
            `event_types` is not provided, this parameter defaults to `None`.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              example: ["message"]
        - $ref: "#/components/parameters/Narrow"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      queue_id:
                        type: string
                        description: |
                          The ID of the queue that has been allocated for your client.
                      last_event_id:
                        type: integer
                        description: |
                          The initial value of `last_event_id` to pass to `GET /api/v1/events`.
                      zulip_feature_level:
                        type: integer
                        description: |
                          The server's current [Zulip feature level](/api/changelog).
                      zulip_version:
                        type: string
                        description: |
                          The server's version.
                  - example:
                      {
                        "last_event_id": -1,
                        "msg": "",
                        "queue_id": "1517975029:0",
                        "realm_emoji":
                          {
                            "1":
                              {
                                "author_id": 5,
                                "deactivated": false,
                                "id": "1",
                                "name": "green_tick",
                                "source_url": "/user_avatars/1/emoji/images/1.png",
                              },
                          },
                        "result": "success",
                        "zulip_feature_level": 2,
                        "zulip_version": "2.1.0",
                      }
  /server_settings:
    get:
      operationId: get_server_settings
      tags: ["server_and_organizations"]
      description: |
        Fetch global settings for a Zulip server.

        `GET {{ api_url }}/v1/server_settings`

        **Note:** this endpoint does not require any authentication at all, and you can use it to check:

        * If this is a Zulip server, and if so, what version of Zulip it's running.
        * What a Zulip client (e.g. a mobile app or
        [zulip-terminal](https://github.com/zulip/zulip-terminal/)) needs to
        know in order to display a login prompt for the server (e.g. what
        authentication methods are available).
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      authentication_methods:
                        type: object
                        additionalProperties: false
                        deprecated: true
                        description: |
                          Each key-value pair in the object indicates whether the authentication
                          method is enabled on this server.

                          **Changes**: Deprecated in Zulip 2.1, in favor of the more expressive
                          `external_authentication_methods`.
                        properties:
                          password:
                            description: |
                              Whether the user can authenticate using password.
                            type: boolean
                          dev:
                            description: |
                              Whether the user can authenticate using development api key.
                            type: boolean
                          email:
                            description: |
                              Whether the user can authenticate using email.
                            type: boolean
                          ldap:
                            description: |
                              Whether the user can authenticate using ldap.
                            type: boolean
                          remoteuser:
                            description: |
                              Whether the user can authenticate using remoteuser.
                            type: boolean
                          github:
                            description: |
                              Whether the user can authenticate using their github account.
                            type: boolean
                          azuread:
                            description: |
                              Whether the user can authenticate using their azuread account.
                            type: boolean
                          gitlab:
                            description: |
                              Whether the user can authenticate using their gitlab account.
                            type: boolean
                          apple:
                            description: |
                              Whether the user can authenticate using their apple account.
                            type: boolean
                          google:
                            description: |
                              Whether the user can authenticate using their google account.
                            type: boolean
                          saml:
                            description: |
                              Whether the user can authenticate using saml.
                            type: boolean
                      external_authentication_methods:
                        type: array
                        description: |
                          A list of dictionaries describing the available external
                          authentication methods (E.g. Google, GitHub, or SAML)
                          enabled for this organization.

                          The list is sorted in the order in which these
                          authentication methods should be displayed.

                          **Changes**: New in Zulip 2.1.
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            name:
                              type: string
                              description: |
                                A unique, table, machine-readable name for the authentication method,
                                intended to be used by clients with special behavior for specific
                                authenatication methods to correctly identify the method.
                            display_name:
                              type: string
                              description: |
                                Display name of the authentication method, to be used in all buttons
                                for the authentication method.
                            display_icon:
                              type: string
                              nullable: true
                              description: |
                                URL for an image to be displayed as an icon in all buttons for
                                the external authentication method.

                                When null, no icon should be displayed.
                            login_url:
                              type: string
                              description: |
                                URL to be used to initiate authentication using this method.
                            signup_url:
                              type: string
                              description: |
                                URL to be used to initiate account registration using this method.
                      zulip_version:
                        type: string
                        description: |
                          The version of Zulip running in the server.
                      zulip_feature_level:
                        type: integer
                        description: |
                          An integer indicating what features are
                          available on the server. The feature level increases monotonically;
                          a value of N means the server supports all API features introduced
                          before feature level N.  This is designed to provide a simple way
                          for client apps to decide whether the server supports a given
                          feature or API change.  See the [changelog](/api/changelog) for
                          details on what each feature level means.

                          **Changes**.  New in Zulip 3.0.  We recommend using an implied value
                          of 0 for Zulip servers that do not send this field.
                      push_notifications_enabled:
                        type: boolean
                        description: |
                          Whether mobile/push notifications are enabled.
                      is_incompatible:
                        type: boolean
                        description: |
                          Whether the Zulip client that has sent a request to this endpoint is
                          deemed incompatible with the server.
                      email_auth_enabled:
                        type: boolean
                        description: |
                          Setting for allowing users authenticate with an email-password
                          combination.
                      require_email_format_usernames:
                        type: boolean
                        description: |
                          Whether all valid usernames for authentication to this
                          organization will be email addresses. This is important
                          for clients to know whether to do client side validation
                          of email address format in a login prompt.

                          This value will be false if the server has [LDAP
                          authentication][ldap-auth] enabled with a username and
                          password combination.
                      realm_uri:
                        type: string
                        description: |
                          The organization's canonical URL.
                      realm_name:
                        type: string
                        description: |
                          The organization's name (for display purposes).
                      realm_icon:
                        type: string
                        description: |
                          The URL for the organization's logo formatted as a square image,
                          used for identifying the organization in small locations in the
                          mobile and desktop apps.
                      realm_description:
                        type: string
                        description: |
                          HTML description of the organization, as configured by the [organization
                          profile](/help/create-your-organization-profile).
                  - example:
                      {
                        "authentication_methods":
                          {
                            "password": true,
                            "dev": true,
                            "email": true,
                            "ldap": false,
                            "remoteuser": false,
                            "github": true,
                            "azuread": false,
                            "google": true,
                            "saml": true,
                          },
                        "zulip_version": "2.0.6+git",
                        "push_notifications_enabled": false,
                        "msg": "",
                        "is_incompatible": false,
                        "email_auth_enabled": true,
                        "require_email_format_usernames": true,
                        "realm_uri": "http://localhost:9991",
                        "realm_name": "Zulip Dev",
                        "realm_icon": "https://secure.gravatar.com/avatar/62429d594b6ffc712f54aee976a18b44?d=identicon",
                        "realm_description": "<p>The Zulip development environment default organization.  It's great for testing!</p>",
                        "result": "success",
                        "external_authentication_methods":
                          [
                            {
                              "name": "saml:idp_name",
                              "display_name": "SAML",
                              "display_icon": null,
                              "login_url": "/accounts/login/social/saml/idp_name",
                              "signup_url": "/accounts/register/social/saml/idp_name",
                            },
                            {
                              "name": "google",
                              "display_name": "Google",
                              "display_icon": "/static/images/landing-page/logos/googl_e-icon.png",
                              "login_url": "/accounts/login/social/google",
                              "signup_url": "/accounts/register/social/google",
                            },
                            {
                              "name": "github",
                              "display_name": "GitHub",
                              "display_icon": "/static/images/landing-page/logos/github-icon.png",
                              "login_url": "/accounts/login/social/github",
                              "signup_url": "/accounts/register/social/github",
                            },
                          ],
                      }
  /settings/notifications:
    patch:
      operationId: update_notification_settings
      tags: ["users"]
      description: |
        This endpoint is used to edit the user's global notification settings.
        See [this endpoint](/api/update-subscription-settings) for
        per-stream notification settings.

        `PATCH {{ api_url }}/v1/settings/notifications`
      parameters:
        - name: enable_stream_desktop_notifications
          in: query
          description: |
            Enable visual desktop notifications for stream messages.
          schema:
            type: boolean
          example: true
        - name: enable_stream_email_notifications
          in: query
          description: |
            Enable email notifications for stream messages.
          schema:
            type: boolean
          example: true
        - name: enable_stream_push_notifications
          in: query
          description: |
            Enable mobile notifications for stream messages.
          schema:
            type: boolean
          example: true
        - name: enable_stream_audible_notifications
          in: query
          description: |
            Enable audible desktop notifications for stream messages.
          schema:
            type: boolean
          example: true
        - name: notification_sound
          in: query
          description: |
            Notification sound name.
          content:
            application/json:
              schema:
                type: string
              example: ding
        - name: enable_desktop_notifications
          in: query
          description: |
            Enable visual desktop notifications for private messages and @-mentions.
          schema:
            type: boolean
          example: true
        - name: enable_sounds
          in: query
          description: |
            Enable audible desktop notifications for private messages and
            @-mentions.
          schema:
            type: boolean
          example: true
        - name: enable_offline_email_notifications
          in: query
          description: |
            Enable email notifications for private messages and @-mentions received
            when the user is offline.
          schema:
            type: boolean
          example: true
        - name: enable_offline_push_notifications
          in: query
          description: |
            Enable mobile notification for private messages and @-mentions received
            when the user is offline.
          schema:
            type: boolean
          example: true
        - name: enable_online_push_notifications
          in: query
          description: |
            Enable mobile notification for private messages and @-mentions received
            when the user is online.
          schema:
            type: boolean
          example: true
        - name: enable_digest_emails
          in: query
          description: |
            Enable digest emails when the user is away.
          schema:
            type: boolean
          example: true
        - name: enable_login_emails
          in: query
          description: |
            Enable email notifications for new logins to account.
          schema:
            type: boolean
          example: true
        - name: message_content_in_email_notifications
          in: query
          description: |
            Include the message's content in missed messages email notifications.
          schema:
            type: boolean
          example: true
        - name: pm_content_in_desktop_notifications
          in: query
          description: |
            Include content of private messages in desktop notifications.
          schema:
            type: boolean
          example: true
        - name: wildcard_mentions_notify
          in: query
          description: |
            Whether wildcard mentions (E.g. @**all**) should send notifications
            like a personal mention.
          schema:
            type: boolean
          example: true
        - name: desktop_icon_count_display
          in: query
          description: |
            Unread count summary (appears in desktop sidebar and browser tab)

            * 1 - All unreads
            * 2 - Private messages and mentions
            * 3 - None
          content:
            application/json:
              schema:
                type: integer
                enum:
                  - 1
                  - 2
                  - 3
              example: 1
        - name: realm_name_in_notifications
          in: query
          description: |
            Include organization name in subject of missed message emails.
          schema:
            type: boolean
          example: true
        - name: presence_enabled
          in: query
          description: |
            Display the presence status to other users when online.
          schema:
            type: boolean
          example: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      enable_desktop_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_desktop_notifications`, if it was changed in
                          this request.
                      enable_digest_emails:
                        type: boolean
                        description: |
                          The setting for `enable_digest_emails`, if it was changed in this
                          request.
                      enable_offline_email_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_offline_email_notifications`, if it was changed
                          in this request.
                      enable_offline_push_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_offline_push_notifications`, if it was changed
                          in this request.
                      enable_online_push_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_online_push_notifications`, if it was changed in
                          this request.
                      enable_sounds:
                        type: boolean
                        description: |
                          The setting for `enable_sounds`, if it was changed in this request.
                      enable_stream_email_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_stream_email_notifications`, if it was changed
                          in this request.
                      enable_stream_push_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_stream_push_notifications`, if it was changed in
                          this request.
                      enable_stream_audible_notifications:
                        type: boolean
                        description: |
                          The setting for `enable_stream_audible_notifications`, if it was changed
                          in this request.
                      message_content_in_email_notifications:
                        type: boolean
                        description: |
                          The setting for `message_content_in_email_notifications`, if it was
                          changed in this request.
                  - example:
                      {
                        "enable_offline_push_notifications": true,
                        "enable_online_push_notifications": true,
                        "msg": "",
                        "result": "success",
                      }
  /streams:
    get:
      operationId: get_streams
      tags: ["streams"]
      description: |
        Get all streams that the user has access to.

        `GET {{ api_url }}/v1/streams`
      parameters:
        - name: include_public
          in: query
          description: |
            Include all public streams.
          schema:
            type: boolean
            default: true
          example: false
        - name: include_subscribed
          in: query
          description: |
            Include all streams that the user is subscribed to.
          schema:
            type: boolean
            default: true
          example: false
        - name: include_all_active
          in: query
          description: |
            Include all active streams. The user must have administrative privileges
            to use this parameter.
          schema:
            type: boolean
            default: false
          example: true
        - name: include_default
          in: query
          description: |
            Include all default streams for the user's realm.
          schema:
            type: boolean
            default: false
          example: true
        - name: include_owner_subscribed
          in: query
          description: |
            If the user is a bot, include all streams that the bot's owner is
            subscribed to.
          schema:
            type: boolean
            default: false
          example: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      streams:
                        description: |
                          A list of `stream` objects with details on the requested streams.
                        type: array
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            stream_id:
                              type: integer
                              description: |
                                The unique ID of the stream.
                            name:
                              type: string
                              description: |
                                The name of the stream.
                            description:
                              type: string
                              description: |
                                The short description of the stream in text/markdown format,
                                intended to be used to prepopulate UI for editing a stream's
                                description.
                            invite_only:
                              type: boolean
                              description: |
                                Specifies whether the stream is private or not.
                                Only people who have been invited can access a private stream.
                            rendered_description:
                              type: string
                              description: |
                                The short description of the stream rendered as HTML, intended to
                                be used when displaying the stream description in a UI.

                                One should use the standard Zulip rendered_markdown CSS when
                                displaying this content so that emoji, LaTeX, and other syntax
                                work correctly.  And any client-side security logic for
                                user-generated message content should be applied when displaying
                                this HTML as though it were the body of a Zulip message.
                            is_web_public:
                              type: boolean
                              description: |
                                Whether the stream has been configured to allow unauthenticated
                                access to its message history from the web.
                            stream_post_policy:
                              type: integer
                              description: |
                                Policy for which users can post messages to the stream.

                                * 1 => Any user can post.
                                * 2 => Only administrators can post.
                                * 3 => Only new members can post.

                                **Changes**: New in Zulip 3.0, replacing the previous
                                `is_announcement_only` boolean.
                            message_retention_days:
                              type: integer
                              nullable: true
                              description: |
                                Number of days that messages sent to this stream will be stored
                                before being automatically deleted by the [message retention
                                policy](/help/message-retention-policy).  There are two special values:

                                * `null`, the default, means the stream will inherit the organization
                                  level setting.
                                * `-1` encodes retaining messages in this stream forever.

                                **Changes**: New in Zulip 3.0 (feature level 17).
                            history_public_to_subscribers:
                              type: boolean
                              description: |
                                Whether the history of the stream is public to its subscribers.

                                Currently always true for public streams (i.e. invite_only=False implies
                                history_public_to_subscribers=True), but clients should not make that
                                assumption, as we may change that behavior in the future.
                            first_message_id:
                              type: integer
                              nullable: true
                              description: |
                                The id of the first message in the stream.

                                Intended to help clients determine whether they need to display
                                UI like the "more topics" widget that would suggest the stream
                                has older history that can be accessed.

                                Null is used for streams with no message history.
                            is_announcement_only:
                              type: boolean
                              deprecated: true
                              description: |
                                Whether the given stream is announcement only or not.

                                **Changes**: Deprecated in Zulip 3.0 (feature level 1), use
                                `stream_post_policy` instead.
                            is_default:
                              type: boolean
                              description: |
                                Whether the given stream is a
                                [default stream](/help/set-default-streams-for-new-users).  Only
                                returned if the `include_default` parameter is `true`.
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "streams":
                          [
                            {
                              "description": "A Scandinavian country",
                              "invite_only": false,
                              "name": "Denmark",
                              "stream_id": 1,
                            },
                            {
                              "description": "Yet another Italian city",
                              "invite_only": false,
                              "name": "Rome",
                              "stream_id": 2,
                            },
                            {
                              "description": "Located in the United Kingdom",
                              "invite_only": false,
                              "name": "Scotland",
                              "stream_id": 3,
                            },
                            {
                              "description": "A northeastern Italian city",
                              "invite_only": false,
                              "name": "Venice",
                              "stream_id": 4,
                            },
                            {
                              "description": "A city in Italy",
                              "invite_only": false,
                              "name": "Verona",
                              "stream_id": 5,
                            },
                            {
                              "description": "New stream for testing",
                              "invite_only": false,
                              "name": "new stream",
                              "stream_id": 6,
                            },
                          ],
                      }
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/CodedError"
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "User not authorized for this query",
                        "result": "error",
                      }
  /streams/{stream_id}:
    delete:
      operationId: delete_stream
      tags: ["streams"]
      description: |
        [Delete the stream](/help/delete-a-stream) with the ID `stream_id`.

        `DELETE {{ api_url }}/v1/streams/{stream_id}`
      parameters:
        - $ref: "#/components/parameters/StreamIdInPath"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"msg": "", "result": "success"}
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - properties:
                      msg:
                        type: string
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "Invalid stream id",
                        "result": "error",
                      }
    patch:
      operationId: update_stream
      tags: ["streams"]
      description: |
        Configure the stream with the ID `stream_id`.  This endpoint supports
        an organization administrator editing any property of a stream,
        including:

        * Stream [name](/help/rename-a-stream) and [description](/help/change-the-stream-description)
        * Stream [permissions](/help/stream-permissions), including
        [privacy](/help/change-the-privacy-of-a-stream) and [who can
        send](/help/stream-sending-policy).

        `PATCH {{ api_url }}/v1/streams/{stream_id}`
      parameters:
        - $ref: "#/components/parameters/StreamIdInPath"
        - name: description
          in: query
          description: |
            The new description for the stream.
          content:
            application/json:
              schema:
                type: string
              example: This stream is related to football dicsussions.
          required: false
        - name: new_name
          in: query
          description: |
            The new name for the stream.
          content:
            application/json:
              schema:
                type: string
              example: Italy
          required: false
        - name: is_private
          in: query
          description: |
            Change whether the stream is a private stream.
          schema:
            type: boolean
          example: true
          required: false
        - name: is_announcement_only
          in: query
          deprecated: true
          description: |
            Whether the stream is limited to announcements.

            **Changes**: Deprecated in Zulip 3.0 (feature level 1), use
              `stream_post_policy` instead.
          schema:
            type: boolean
          example: true
          required: false
        - $ref: "#/components/parameters/StreamPostPolicy"
        - $ref: "#/components/parameters/HistoryPublicToSubscribers"
        - $ref: "#/components/parameters/MessageRetentionDays"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"msg": "", "result": "success"}
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "Invalid stream id",
                        "result": "error",
                      }
  /typing:
    post:
      operationId: set_typing_status
      tags: ["users"]
      description: |
        Send an event indicating that the user has started or stopped typing
        on their client.  See
        [the typing notification docs](https://zulip.readthedocs.io/en/latest/subsystems/typing-indicators.html)
        for details on Zulip's typing notifications protocol.

        `POST {{ api_url }}/v1/typing`
      parameters:
        - name: op
          in: query
          description: |
            Whether the user has started (`start`) or stopped (`stop`) to type.
          schema:
            type: string
            enum:
              - start
              - stop
          example: start
          required: true
        - name: to
          in: query
          description: |
            The user_ids of the recipients of the message being typed. Typing
            notifications are only supported for private messages. Send a
            JSON-encoded list of user_ids. (Use a list even if there is only one
            recipient.).

            **Changes**: Before Zulip 2.0, this parameter accepted only a JSON-encoded
            list of email addresses.  Support for the email address-based format was
            removed in Zulip 3.0 (feature level 11).
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
              example: [9, 10]
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JsonSuccess"

  /user_groups/create:
    post:
      operationId: create_user_group
      tags: ["users"]
      description: |
        Create a new [user group](/help/user-groups).

        `POST {{ api_url }}/v1/user_groups/create`
      parameters:
        - name: name
          in: query
          description: |
            The name of the user group.
          schema:
            type: string
          example: marketing
          required: true
        - name: description
          in: query
          description: |
            The description of the user group.
          schema:
            type: string
          example: The marketing team.
          required: true
        - name: members
          in: query
          description: |
            An array containing the user IDs of the initial members for the
            new user group.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
              example: [1, 2, 3, 4]
          required: true
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"msg": "", "result": "success"}
        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "result": "error",
                        "code": "BAD_REQUEST",
                        "msg": "Invalid user ID: 500",
                      }
  /user_groups/{group_id}:
    patch:
      operationId: update_user_group
      tags: ["users"]
      description: |
        Update the name or description of a [user group](/help/user-groups).

        `PATCH {{ api_url }}/v1/user_groups/{group_id}`
      parameters:
        - $ref: "#/components/parameters/GroupId"
        - name: name
          in: query
          description: |
            The new name of the group.
          schema:
            type: string
          example: marketing team
          required: true
        - name: description
          in: query
          description: |
            The new description of the group.
          schema:
            type: string
          example: The marketing team.
          required: true
      responses:
        "200":
          $ref: "#/components/responses/SimpleSuccess"

        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "Invalid user group",
                        "result": "error",
                      }
    delete:
      operationId: remove_user_group
      tags: ["users"]
      description: |
        Delete a [user group](/help/user-groups).

        `DELETE {{ api_url }}/v1/user_groups/{group_id}`
      parameters:
        - $ref: "#/components/parameters/GroupId"
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - example: {"result": "success", "msg": ""}

        "400":
          description: Bad request.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonError"
                  - example:
                      {
                        "code": "BAD_REQUEST",
                        "msg": "Invalid user group",
                        "result": "error",
                      }

  /user_groups:
    get:
      operationId: get_user_groups
      tags: ["users"]
      description: |
        Fetches all of the user groups in the organization.

        `GET {{ api_url }}/v1/user_groups`
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      user_groups:
                        type: array
                        items:
                          type: object
                          additionalProperties: false
                          properties:
                            description:
                              type: string
                              description: |
                                The human-readable description of the user group.
                            id:
                              type: integer
                              description: |
                                The user group's integer id.
                            members:
                              type: array
                              description: |
                                The integer User IDs of the user group members.
                              items:
                                type: integer
                            name:
                              type: string
                              description: |
                                User group name.
                        description: |
                          A list of `user_group` objects, which contain a `description`, a `name`,
                          their `id` and the list of members of the user group.
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "user_groups":
                          [
                            {
                              "description": "Characters of Hamlet",
                              "id": 1,
                              "name": "hamletcharacters",
                              "members": [3, 4],
                            },
                            {
                              "description": "Other users",
                              "id": 2,
                              "name": "other users",
                              "members": [1, 2],
                            },
                          ],
                      }
  /real-time:
    # This entry is a hack; it exists to give us a place to put the text
    # documenting the parameters for call_on_each_event and friends.
    post:
      tags: ["real_time_events"]
      description: |
        (Ignored)
      parameters:
        - $ref: "#/components/parameters/Narrow"
        - $ref: "#/components/parameters/Event_types"
      security:
        - basicAuth: []
      responses:
        # Makeshift response for this hack entry.
        "200":
          description: Success
  /rest-error-handling:
    post:
      operationId: rest_error_handling
      tags: ["real_time_events"]
      description: |
        Common error to many endpoints
      responses:
        "400":
          description: |
            Bad request.
          content:
            application/json:
              schema:
                oneOf:
                  - allOf:
                      - $ref: "#/components/schemas/InvalidApiKeyError"
                  - allOf:
                      - $ref: "#/components/schemas/MissingArgumentError"
                  - allOf:
                      - $ref: "#/components/schemas/UserNotAuthorizedError"
  /zulip-outgoing-webhook:
    post:
      operationId: zulip_outgoing_webhooks
      tags: ["webhooks"]
      description: |
        Outgoing Webhooks allows to build or set up Zulip integrations which are
        notified when certain types of messages are sent in Zulip.
      responses:
        "200":
          description: |
            Success
          content:
            application/json:
              schema:
                additionalProperties: false
                properties:
                  data:
                    type: string
                    description: |
                      The message content, in raw markdown format (not rendered to HTML).
                  trigger:
                    type: string
                    description: |
                      What aspect of the message triggered the outgoing webhook notification.
                      Possible values include `private_message` and `mention`.
                  token:
                    type: string
                    description: |
                      A string of alphanumeric characters that can be use to authenticate the
                      webhook request.  You can get the token used by a given outgoing webhook bot
                      in the `zuliprc` file downloaded when creating the bot.
                  message:
                    allOf:
                      - description: |
                          A dict containing details on the message that triggered the
                          outgoing webhook, in the format used by [`GET /messages`](/api/get-messages).
                      - $ref: "#/components/schemas/Messages"
                  bot_email:
                    type: string
                    description: |
                      Email of the bot user.
                example:
                  {
                    "data": "@**Outgoing Webhook Test** Zulip is the world\u2019s most productive group chat!",
                    "trigger": "mention",
                    "token": "xvOzfurIutdRRVLzpXrIIHXJvNfaJLJ0",
                    "message":
                      {
                        "subject": "Verona2",
                        "sender_email": "iago@zulip.com",
                        "timestamp": 1527876931,
                        "client": "website",
                        "submessages": [],
                        "recipient_id": 20,
                        "topic_links": [],
                        "sender_full_name": "Iago",
                        "avatar_url": "https://secure.gravatar.com/avatar/1f4f1575bf002ae562fea8fc4b861b09?d=identicon&version=1",
                        "rendered_content": "<p><span class=\"user-mention\" data-user-id=\"25\">@Outgoing Webhook Test</span> Zulip is the world\u2019s most productive group chat!</p>",
                        "sender_id": 5,
                        "stream_id": 5,
                        "content": "@**Outgoing Webhook Test** Zulip is the world\u2019s most productive group chat!",
                        "display_recipient": "Verona",
                        "type": "stream",
                        "id": 112,
                        "is_me_message": false,
                        "reactions": [],
                        "sender_realm_str": "zulip",
                      },
                    "bot_email": "outgoing-bot@localhost",
                  }

  /calls/bigbluebutton/create:
    get:
      tags: ["streams"]
      operationId: create_big_blue_button_video_call
      description: |
        Create a video call url for a Big Blue Button video call.
        Requires Big Blue Button to be configured on the Zulip server.
      responses:
        "200":
          description: Success.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/JsonSuccess"
                  - properties:
                      url:
                        description: |
                          The url for the Big Blue Button video call.
                        type: string
                        example: "/calls/bbb/join?meeting_id=%22zulip-something%22&password=%22something%22&checksum=%22somechecksum%22"
                  - example:
                      {
                        "msg": "",
                        "result": "success",
                        "url": "/calls/bbb/join?meeting_id=%22zulip-something%22&password=%22something%22&checksum=%22somechecksum%22",
                      }

components:
  #######################
  # Security definitions
  #######################
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
      description: |
        Basic authentication, with the user's email as the username, and the API
        key as the password. The API key can be fetched using the
        `/fetch_api_key` or `/dev_fetch_api_key` endpoints.

  schemas:
    Messages:
      type: object
      additionalProperties: false
      properties:
        avatar_url:
          type: string
          nullable: true
          description: |
            The URL of the user's avatar.  Can be null only if client_gravatar was passed,
            which means that the user has not uploaded an avatar in Zulip, and the
            client should compute the gravatar URL by hashing the
            user's email address itself for this user.
        client:
          type: string
          description: |
            A Zulip "client" string, describing what Zulip client
            sent the message.
        content:
          type: string
          description: |
            The content/body of the message.
        rendered_content:
          type: string
          description: |
            The content/body of the message rendered in HTML.
        content_type:
          type: string
          description: |
            The HTTP `content_type` for the message content.  This
            will be `text/html` or `text/x-markdown`, depending on
            whether `apply_markdown` was set.
        display_recipient:
          oneOf:
            - type: string
            - type: array
              items:
                type: object
                additionalProperties: false
                properties:
                  id:
                    type: integer
                    description: |
                      ID of the user.
                  email:
                    type: string
                    description: |
                      Email of the user.
                  full_name:
                    type: string
                    description: |
                      Full name of the user.
                  is_mirror_dummy:
                    type: boolean
                    description: |
                      Whether the user is a mirror dummy.
          description: |
            Data on the recipient of the message;
            either the name of a stream or a dictionary containing basic data on
            the users who received the message.
        flags:
          type: array
          description: |
            The user's [message flags][message-flags] for the message.
          items:
            type: string
        id:
          type: integer
          description: |
            The unique message ID.  Messages should always be
            displayed sorted by ID.
        is_me_message:
          type: boolean
          description: |
            Whether the message is a [/me status message][status-messages]
        reactions:
          type: array
          description: |
            Data on any reactions to the message.
          items:
            type: object
            additionalProperties: false
            properties:
              emoji_code:
                type: string
                description: |
                  A unique identifier, defining the specific emoji codepoint requested,
                  within the namespace of the `reaction_type`.

                  For example, for `unicode_emoji`, this will be an encoding of the
                  unicode codepoint.
              emoji_name:
                type: string
                description: |
                  Name of the emoji.
              reaction_type:
                type: string
                description: |
                  One of the following values:

                  * `unicode_emoji`: Unicode emoji (`emoji_code` will be its unicode
                    codepoint).
                  * `realm_emoji`: [Custom emoji](/help/add-custom-emoji).
                    (`emoji_code` will be its ID).
                  * `zulip_extra_emoji`: Special emoji included with Zulip.  Exists to
                    namespace the `zulip` emoji.
              user_id:
                type: integer
                description: |
                  The ID of the user who added the reaction.

                  **Changes**: New in Zulip 3.0 (feature level 2). The `user`
                  object is deprecated and will be removed in the future.
              user:
                type: object
                additionalProperties: false
                deprecated: true
                description: |
                  Dictionary with data on the user who added the reaction, including
                  the user ID as the `id` field.  **Note**: In the [events
                  API](/api/get-events), this `user` dictionary
                  confusing had the user ID in a field called `user_id`
                  instead.  We recommend ignoring fields other than the user
                  ID.  **Deprecated** and to be removed in a future release
                  once core clients have migrated to use the `user_id` field.
                properties:
                  id:
                    type: integer
                    description: |
                      ID of the user.
                  email:
                    type: string
                    description: |
                      Email of the user.
                  full_name:
                    type: string
                    description: |
                      Full name of the user.
                  is_mirror_dummy:
                    type: boolean
                    description: |
                      Whether the user is a mirror dummy.
        recipient_id:
          type: integer
          description: |
            A unique ID for the set of users receiving the
            message (either a stream or group of users).  Useful primarily
            for hashing.
        sender_email:
          type: string
          description: |
            The Zulip display email address of the message's sender.
        sender_full_name:
          type: string
          description: |
            The full name of the message's sender.
        sender_id:
          type: integer
          description: |
            The user ID of the message's sender.
        sender_realm_str:
          type: string
          description: |
            A string identifier for the realm the sender is in.  Unique only within
            the context of a given Zulip server.

            E.g. on `example.zulip.com`, this will be `example`.
        stream_id:
          type: integer
          description: |
            Only present for stream messages; the ID of the stream.
        subject:
          type: string
          description: |
            The `topic` of the message (only present for stream
            messages).  The field name is a legacy holdover from when topics were
            called "subjects" and will eventually change.
        topic_links:
          type: array
          items:
            type: string
          description: |
            Data on any links to be included in the `topic`
            line (these are generated by [custom linkification
            filters][linkification-filters] that match content in the
            message's topic.)

            **Changes**: New in Zulip 3.0 (feature level 1).
            Previously, this field was called `subject_links`;
            clients are recommended to rename `subject_links`
            to `topic_links` if present for compatibility with
            older Zulip servers.
        submessages:
          type: array
          items:
            type: string
          description: |
            Data used for certain experimental Zulip integrations.
        timestamp:
          type: integer
          description: |
            The UNIX timestamp for when the message was sent,
            in UTC seconds.
        last_edit_timestamp:
          type: integer
          description: |
            The UNIX timestamp for when the message was last edited,
            in UTC seconds.
        type:
          type: string
          description: |
            The type of the message: `stream` or `private`.
        match_content:
          type: string
          description: |
            Only present if keyword search was included among the narrow parameters.
            HTML content of a queried message that matches the narrow, with
            `<span class="highlight">` elements wrapping the matches for the
            search keywords.
        match_subject:
          type: string
          description: |
            Only present if keyword search was included among the narrow parameters.
            HTML-escaped topic of a queried message that matches the narrow, with
            `<span class="highlight">` elements wrapping the matches for the
            search keywords.
    User:
      type: object
      additionalProperties: false
      description: |
        A dictionary containing basic data on a given Zulip user.
      properties:
        email:
          type: string
          description: |
            The Zulip API email address of the user or bot.

            If you do not have permission to view the email address of the target user,
            this will be a fake email address that is usable for the Zulip API but nothing else.
        is_bot:
          type: boolean
          description: |
            A boolean specifying whether the user is a bot or full account.
        avatar_url:
          type: string
          nullable: true
          description: |
            URL for the the user's avatar.  Will be `null` if the `client_gravatar`
            query parameter was set to `True` and the user's avatar is hosted by
            the Gravatar provider (i.e. the user has never uploaded an avatar).
        avatar_version:
          type: integer
          description: |
            Version for the the user's avatar.  Used for cache-busting requests
            for the user's avatar.  Clients generally shouldn't need to use this;
            most avatar URLs sent by Zulip will already end with `?v={avatar_version}`.
        full_name:
          type: string
          description: |
            Full name of the user or bot, used for all display purposes.
        is_admin:
          type: boolean
          description: |
            A boolean specifying whether the user is an organization administrator.
        is_owner:
          type: boolean
          description: |
            A boolean specifying whether the user is an organization owner.
            If true, is_admin will also be true.

            **Changes**: New in Zulip 3.0 (feature level 8).
        bot_type:
          type: integer
          nullable: true
          description: |
            An integer describing the type of bot:
            * `null` if the user isn't a bot.
            * `1` for a `Generic` bot.
            * `2` for an `Incoming webhook` bot.
            * `3` for an `Outgoing webhook` bot.
            * `4` for an `Embedded` bot.
        user_id:
          type: integer
          description: |
            The unique ID of the user.
        bot_owner_id:
          type: integer
          nullable: true
          description: |
            If the user is a bot (i.e. `is_bot` is `True`),
            `bot_owner` is the user ID of the bot's owner (usually, whoever
            created the bot).

            Will be null for legacy bots that do not have an owner.

            **Changes**: New in Zulip 3.0 (feature level
            1).  In previous versions, there was a `bot_owner` field
            containing the email address of the bot's owner.
        is_active:
          type: boolean
          description: |
            A boolean specifying whether the user account has been deactivated.
        is_guest:
          type: boolean
          description: |
            A boolean specifying whether the user is a guest user.
        timezone:
          type: string
          description: |
            The time zone of the user.
        date_joined:
          type: string
          description: |
            The time the user account was created.
        delivery_email:
          type: string
          description: |
            The user's real email address.  This field is present only if
            [email address visibility](/help/restrict-visibility-of-email-addresses) is
            limited and you are an administrator with access to real email addresses
            under the configured policy.
        profile_data:
          $ref: "#/components/schemas/profile_data"
    profile_data:
      type: object
      description: |
        A dictionary containing custom profile field data for the user. Each entry
        maps the integer ID of a custom profile field in the organization to a
        dictionary containing the user's data for that field.  Generally the data
        includes just a single `value` key; for those custom profile fields
        supporting markdown, a `rendered_value` key will also be present.
      additionalProperties:
        type: object
        additionalProperties: false
        description: |
          '{id}': Object with data about what value user filled in the custom
                      profile field with id `id`.
        properties:
          value:
            type: string
            description: |
              User's personal value for this custom profile field.
          rendered_value:
            type: string
            description: |
              The `value` rendered in HTML.  Will only be present for
              custom profile field types that support markdown rendering.

              This user-generated HTML content should be rendered
              using the same CSS and client-side security protections
              as are used for message content.
    JsonResponse:
      type: object
      additionalProperties: false
      properties:
        result:
          type: string
    JsonSuccess:
      allOf:
        - $ref: "#/components/schemas/JsonResponse"
        - required:
            - result
            - msg
        - properties:
            result:
              enum:
                - success
            msg:
              type: string
        - example: {"msg": "", "result": "success"}
    JsonError:
      allOf:
        - $ref: "#/components/schemas/JsonResponse"
        - required:
            - result
            - msg
        - properties:
            result:
              enum:
                - error
            msg:
              type: string
    ApiKeyResponse:
      allOf:
        - $ref: "#/components/schemas/JsonSuccess"
        - required:
            - api_key
            - email
        - properties:
            api_key:
              type: string
              description: |
                The API key that can be used to authenticate as the requested user.
            email:
              type: string
              description: |
                The email address of the user who owns the API key
        - example:
            {
              "api_key": "gjA04ZYcqXKalvYMA8OeXSfzUOLrtbZv",
              "email": "iago@zulip.com",
              "msg": "",
              "result": "success",
            }
    CodedError:
      allOf:
        - $ref: "#/components/schemas/JsonError"
        - properties:
            code:
              type: string
              description: |
                A string that identifies the error.
    BadEventQueueIdError:
      allOf:
        - $ref: "#/components/schemas/CodedError"
        - properties:
            queue_id:
              type: string
              description: |
                The string that identifies the invalid event queue.
        - example:
            {
              "code": "BAD_EVENT_QUEUE_ID",
              "msg": "Bad event queue id: 1518820930:1",
              "queue_id": "1518820930:1",
              "result": "error",
            }
    InvalidMessageError:
      allOf:
        - $ref: "#/components/schemas/JsonSuccess"
        - properties:
            raw_content:
              type: string
              description: |
                The raw content of the message.
        - example:
            {
              "msg": "Invalid message(s)",
              "code": "BAD_REQUEST",
              "result": "error",
            }
    NonExistingStreamError:
      allOf:
        - $ref: "#/components/schemas/CodedError"
        - properties:
            stream:
              type: string
              description: |
                The name of the stream that could not be found.
        - example:
            {
              "code": "STREAM_DOES_NOT_EXIST",
              "msg": "Stream 'nonexistent_stream' does not exist",
              "result": "error",
              "stream": "nonexistent_stream",
            }
    AddSubscriptionsResponse:
      allOf:
        - $ref: "#/components/schemas/JsonSuccess"
        - properties:
            subscribed:
              type: object
              description: |
                A dictionary where the key is the email address of the user/bot and the
                value is a list of the names of the streams that were subscribed to as a
                result of the query.
              additionalProperties:
                description: |
                  `{email_address}`: List of the names of the streams that were subscribed
                   to as a result of the query.
                type: array
                items:
                  type: string
            already_subscribed:
              type: object
              description: |
                A dictionary where the key is the email address of the user/bot and the
                value is a list of the names of the streams that the user/bot is already
                subscribed to.
              additionalProperties:
                description: |
                  {email_address}`: List of the names of the streams that the user is
                  already subscribed to.
                type: array
                items:
                  type: string
            unauthorized:
              type: array
              items:
                type: string
              description: |
                A list of names of streams that the requesting user/bot was not
                authorized to subscribe to.  Only present if `authorization_errors_fatal=false`.
    InvalidApiKeyError:
      allOf:
        - $ref: "#/components/schemas/JsonError"
        - example: {"msg": "Invalid API key", "result": "error"}
    MissingArgumentError:
      allOf:
        - $ref: "#/components/schemas/CodedError"
        - properties:
            var_name:
              type: string
              description: |
                It contains the information about the missing parameter.
        - example:
            {
              "code": "REQUEST_VARIABLE_MISSING",
              "msg": "Missing 'content' argument",
              "result": "error",
              "var_name": "content",
            }
    UserNotAuthorizedError:
      allOf:
        - $ref: "#/components/schemas/CodedError"
        - example:
            {
              "code": "BAD_REQUEST",
              "msg": "User not authorized for this query",
              "result": "error",
            }

  ###################
  # Shared responses
  ###################
  responses:
    SimpleSuccess:
      description: Success.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/JsonSuccess"

  ####################
  # Shared parameters
  ####################
  parameters:
    Event_types:
      name: event_types
      in: query
      description: |
        A JSON-encoded array indicating which types of events you're interested
        in. Values that you might find useful include:

          * **message** (messages)
          * **subscription** (changes in your subscriptions)
          * **realm_user** (changes to users in the organization and
            their properties, such as their name).

        If you do not specify this parameter, you will receive all
        events, and have to filter out the events not relevant to
        your client in your client code.  For most applications, one
        is only interested in messages, so one specifies:
        `event_types=['message']`
      content:
        application/json:
          schema:
            type: array
            items:
              type: string
          example: ["message"]
      required: false
    Narrow:
      name: narrow
      in: query
      description: |
        A JSON-encoded array of arrays of length 2 indicating the
        narrow for which you'd like to receive events for. For
        instance, to receive events for the stream `Denmark`, you
        would specify `narrow=[['stream', 'Denmark']]`.  Another
        example is `narrow=[['is', 'private']]` for private messages.
        Default is `[]`.
      content:
        application/json:
          schema:
            type: array
            items:
              type: array
              items:
                type: string
            default: []
          example: [["stream", "Denmark"]]
      required: false
    GroupId:
      name: group_id
      in: path
      description: |
        The ID of the target user group.
      schema:
        type: integer
      example: 42
      required: true
    Topic:
      name: topic
      in: query
      description: |
        The topic of the message. Only required for stream messages
        (`type="stream"`), ignored otherwise.

        Maximum length of 60 characters.

        **Changes**: New in Zulip 2.0.  Previous Zulip releases encoded
        this as `subject`, which is currently a deprecated alias.
      schema:
        type: string
      example: Castle
    QueueId:
      name: queue_id
      in: query
      description: |
        The ID of an event queue that was previously registered via `POST
        /api/v1/register` (see [Register a queue](/api/register-queue)).
      schema:
        type: string
      example: 1375801870:2942
      required: true
    Stream:
      name: stream
      in: query
      description: |
        The name of the stream to access.
      schema:
        type: string
      example: Denmark
    StreamIdInQuery:
      name: stream_id
      in: query
      description: |
        The ID of the stream to access.
      schema:
        type: integer
      example: 42
    StreamIdInPath:
      name: stream_id
      in: path
      description: |
        The ID of the stream to access.
      schema:
        type: integer
      example: 42
      required: true
    ClientGravatar:
      name: client_gravatar
      in: query
      description: |
        Whether the client supports computing gravatars URLs.  If
        enabled, `avatar_url` will be included in the response only
        if there is a Zulip avatar, and will be `null` for users who
        are using gravatar as their avatar.  This option
        significantly reduces the compressed size of user data,
        since gravatar URLs are long, random strings and thus do not
        compress well. The `client_gravatar` field is set to `true` if
        clients can compute their own gravatars.
      schema:
        type: boolean
        default: false
      example: true
    RequiredContent:
      name: content
      in: query
      description: |
        The content of the message. Maximum message size of 10000 bytes.
      schema:
        type: string
      example: Hello
      required: true
    OptionalContent:
      name: content
      in: query
      description: |
        The content of the message. Maximum message size of 10000 bytes.
      schema:
        type: string
      example: Hello
    MessageId:
      name: message_id
      in: path
      description: |
        The target message's ID.
      schema:
        type: integer
      example: 42
      required: true
    UserId:
      name: user_id
      in: path
      description: |
        The target user's ID.
      schema:
        type: integer
      example: 12
      required: true
    StreamPostPolicy:
      name: stream_post_policy
      in: query
      description: |
        Policy for which users can post messages to the stream.

        * 1 => Any user can post.
        * 2 => Only administrators can post.
        * 3 => Only new members can post.

        **Changes**: New in Zulip 3.0, replacing the previous
        `is_announcement_only` boolean.
      schema:
        type: integer
        default: 1
      example: 2
      required: false
    HistoryPublicToSubscribers:
      name: history_public_to_subscribers
      in: query
      description: |
        Whether the stream's message history should be available to
        newly subscribed members, or users can only access messages
        they actually received while subscribed to the stream.

        Corresponds to the [shared history](/help/stream-permissions)
        option in documentation.
      schema:
        type: boolean
      example: false
      required: false

    IncludeSubscribers:
      name: include_subscribers
      in: query
      description: |
        Whether each returned stream object should include a `subscribers`
        field containing a list of the user IDs of its subscribers.

        (This may be significantly slower in organizations with
        thousands of users subscribed to many streams.)

        **Changes**: New in Zulip 2.1.0.
      schema:
        type: boolean
        default: false
      example: true
    EmojiName:
      name: emoji_name
      in: query
      description: |
        The target emoji's human-readable name.

        To find an emoji's name, hover over a message to reveal
        three icons on the right, then click the smiley face icon.
        Images of available reaction emojis appear. Hover over the
        emoji you want, and note that emoji's text name.
      schema:
        type: string
      example: "octopus"
    IncludeCustomProfileFields:
      name: include_custom_profile_fields
      in: query
      description: |
        Whether the client wants [custom profile field](/help/add-custom-profile-fields)
        data to be included in the response.

        **Changes**: New in Zulip 2.1.0.  Previous versions do no offer these
        data via the API.
      schema:
        type: boolean
        default: false
      example: true
    Principals:
      name: principals
      in: query
      description: |
        A list of user ids (preferred) or Zulip display email
        addresses of the users to be subscribed to or unsubscribed
        from the streams specified in the `subscriptions` parameter. If
        not provided, then the requesting user/bot is subscribed.

        **Changes**: The integer format is new in Zulip 3.0 (Feature level 9).
      content:
        application/json:
          schema:
            type: array
            items:
              oneOf:
                - type: string
                - type: integer
          example: ["ZOE@zulip.com"]
    ReactionType:
      name: reaction_type
      in: query
      description: |
        If an app is adding/removing a vote on an existing reaction,
        it should pass this parameter using the value the server provided
        for the existing reaction for specificity.  Supported values:

        * `unicode_emoji`: Unicode emoji (`emoji_code` will be its unicode codepoint).
        * `realm_emoji`: Custom emoji. (`emoji_code` will be its ID).
        * `zulip_extra_emoji`: Special emoji included with Zulip.  Exists to
           namespace the `zulip` emoji.

        **Changes**: In Zulip 3.0 (feature level 2), this become
        optional for [custom emoji](/help/add-custom-emoji);
        previously, this endpoint assumed `unicode_emoji` if this
        parameter was not specified.
      schema:
        type: string
      example: "unicode_emoji"
      required: false
    EmojiCode:
      name: emoji_code
      in: query
      description: |
        A unique identifier, defining the specific emoji codepoint requested,
        within the namespace of the `reaction_type`.

        For most API clients, you won't need this, but it's important
        for Zulip apps to handle rare corner cases when
        adding/removing votes on an emoji reaction added previously by
        another user.

        If the existing reaction was added when the Zulip server was
        using a previous version of the emoji data mapping between
        Unicode codepoints and human-readable names, sending the
        `emoji_code` in the data for the original reaction allows the
        Zulip server to correctly interpret your upvote as an upvote
        rather than a reaction with a "diffenent" emoji.
      schema:
        type: string
      example: "1f419"
      required: false
    MessageRetentionDays:
      name: message_retention_days
      in: query
      description: |
        Number of days that messages sent to this stream will be stored
        before being automatically deleted by the [message retention
        policy](/help/message-retention-policy).  Two special string format
        values are supported:

        * "realm_default" => Return to the organization-level setting.
        * "forever" => Retain messages forever.

        **Changes**: New in Zulip 3.0 (feature level 17).
      schema:
        oneOf:
          - type: string
          - type: integer
      example: "20"
      required: false
