# Copyright 2016 OpenMarket Ltd
# Copyright 2019 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
swagger: '2.0'
info:
  title: "Matrix Client-Server Content Repository API"
  version: "1.0.0"
host: localhost:8008
schemes:
  - https
  - http
basePath: /_matrix/media/%CLIENT_MAJOR_VERSION%
consumes:
  - application/json
  - "*/*"
produces:
  - application/json
  - "*/*"
securityDefinitions:
  $ref: definitions/security.yaml
paths:
  "/upload":
    post:
      summary: Upload some content to the content repository.
      operationId: uploadContent
      produces: ["application/json"]
      security:
        - accessToken: []
      parameters:
        - in: header
          name: Content-Type
          type: string
          description: The content type of the file being uploaded
          x-example: "Content-Type: application/pdf"
        - in: query
          type: string
          x-example: "War and Peace.pdf"
          name: filename
          description: The name of the file being uploaded
        - in: body
          name: "<content>"
          description: The content to be uploaded.
          required: true
          x-example: "<bytes>" # so the spec shows "<bytes>" without quotes.
          schema:
            type: string
            example: "<bytes>"
            format: byte
      responses:
        200:
          description: The `MXC URI`_ for the uploaded content.
          schema:
            type: object
            required: ["content_uri"]
            properties:
              content_uri:
                type: string
                description: "The `MXC URI`_ to the uploaded content."
          examples:
            application/json: {
              "content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
            }
        403:
          description: |-
            The user does not have permission to upload the content. Some reasons for this error include:

            - The server does not permit the file type.
            - The user has reached a quota for uploaded content.
          examples:
            application/json: {
              "errcode": "M_FORBIDDEN",
              "error": "Cannot upload this content"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        413:
          description: |-
            The uploaded content is too large for the server.
          examples:
            application/json: {
              "errcode": "M_TOO_LARGE",
              "error": "Cannot upload files larger than 100mb"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        429:
          description: This request was rate-limited.
          schema:
            "$ref": "definitions/errors/rate_limited.yaml"
      tags:
        - Media
  "/download/{serverName}/{mediaId}":
    get:
      summary: "Download content from the content repository."
      operationId: getContent
      produces: ["*/*"]
      parameters:
        - in: path
          type: string
          name: serverName
          x-example: matrix.org
          required: true
          description: |
            The server name from the ``mxc://`` URI (the authoritory component)
        - in: path
          type: string
          name: mediaId
          x-example: ascERGshawAWawugaAcauga
          required: true
          description: |
            The media ID from the ``mxc://`` URI (the path component)
        - in: query
          type: boolean
          name: allow_remote
          x-example: false
          required: false
          default: true
          description: |
            Indicates to the server that it should not attempt to fetch the media if it is deemed
            remote. This is to prevent routing loops where the server contacts itself. Defaults to
            true if not provided.
      responses:
        200:
          description: "The content that was previously uploaded."
          headers:
            Content-Type:
              description: "The content type of the file that was previously uploaded."
              type: "string"
            Content-Disposition:
              description: |-
                The name of the file that was previously uploaded, if set.
              type: "string"
          schema:
            type: file
            # This is a workaround for us not being able to say the response is required.
            description: "**Required.** The bytes for the uploaded file."
        502:
          description: |-
            The content is too large for the server to serve.
          examples:
            application/json: {
              "errcode": "M_TOO_LARGE",
              "error": "Content is too large to serve"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        429:
          description: This request was rate-limited.
          schema:
            "$ref": "definitions/errors/rate_limited.yaml"
      tags:
        - Media
  "/download/{serverName}/{mediaId}/{fileName}":
    get:
      summary: |-
        Download content from the content repository. This is the same as
        the download endpoint above, except permitting a desired file name.
      operationId: getContentOverrideName
      produces: ["*/*"]
      parameters:
        - in: path
          type: string
          name: serverName
          x-example: matrix.org
          required: true
          description: |
            The server name from the ``mxc://`` URI (the authoritory component)
        - in: path
          type: string
          name: mediaId
          x-example: ascERGshawAWawugaAcauga
          required: true
          description: |
            The media ID from the ``mxc://`` URI (the path component)
        - in: path
          type: string
          name: fileName
          x-example: filename.jpg
          required: true
          description: A filename to give in the ``Content-Disposition`` header.
        - in: query
          type: boolean
          name: allow_remote
          x-example: false
          required: false
          default: true
          description: |
            Indicates to the server that it should not attempt to fetch the media if it is deemed
            remote. This is to prevent routing loops where the server contacts itself. Defaults to
            true if not provided.
      responses:
        200:
          description: "The content that was previously uploaded."
          headers:
            Content-Type:
              description: "The content type of the file that was previously uploaded."
              type: "string"
            Content-Disposition:
              description: |-
                The ``fileName`` requested or the name of the file that was previously
                uploaded, if set.
              type: "string"
          schema:
            type: file
            # This is a workaround for us not being able to say the response is required.
            description: "**Required.** The bytes for the uploaded file."
        502:
          description: |-
            The content is too large for the server to serve.
          examples:
            application/json: {
              "errcode": "M_TOO_LARGE",
              "error": "Content is too large to serve"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        429:
          description: This request was rate-limited.
          schema:
            "$ref": "definitions/errors/rate_limited.yaml"
      tags:
        - Media
  "/thumbnail/{serverName}/{mediaId}":
    get:
      summary: |-
        Download a thumbnail of content from the content repository. See the `thumbnailing <#thumbnails>`_
        section for more information.
      operationId: getContentThumbnail
      produces: ["image/jpeg", "image/png"]
      parameters:
        - in: path
          type: string
          name: serverName
          required: true
          x-example: example.org
          description: |
            The server name from the ``mxc://`` URI (the authoritory component)
        - in: path
          type: string
          name: mediaId
          x-example: ascERGshawAWawugaAcauga
          required: true
          description: |
            The media ID from the ``mxc://`` URI (the path component)
        - in: query
          type: integer
          x-example: 64
          name: width
          required: true
          description: |-
            The *desired* width of the thumbnail. The actual thumbnail may be
            larger than the size specified.
        - in: query
          type: integer
          x-example: 64
          name: height
          required: true
          description: |-
            The *desired* height of the thumbnail. The actual thumbnail may be
            larger than the size specified.
        - in: query
          type: string
          enum: ["crop", "scale"]
          name: method
          x-example: "scale"
          description: |-
            The desired resizing method. See the `thumbnailing <#thumbnails>`_
            section for more information.
        - in: query
          type: boolean
          name: allow_remote
          x-example: false
          required: false
          default: true
          description: |
            Indicates to the server that it should not attempt to fetch the media if it is deemed
            remote. This is to prevent routing loops where the server contacts itself. Defaults to
            true if not provided.
      responses:
        200:
          description: "A thumbnail of the requested content."
          headers:
            Content-Type:
              description: "The content type of the thumbnail."
              type: "string"
              enum: ["image/jpeg", "image/png"]
          schema:
            type: file
            # This is a workaround for us not being able to say the response is required.
            description: "**Required.** The bytes for the thumbnail."
        400:
          description: |-
            The request does not make sense to the server, or the server cannot thumbnail
            the content. For example, the client requested non-integer dimensions or asked
            for negatively-sized images.
          examples:
            application/json: {
              "errcode": "M_UNKNOWN",
              "error": "Cannot generate thumbnails for the requested content"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        413:
          description: |-
            The local content is too large for the server to thumbnail.
          examples:
            application/json: {
              "errcode": "M_TOO_LARGE",
              "error": "Content is too large to thumbnail"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        502:
          description: |-
            The remote content is too large for the server to thumbnail.
          examples:
            application/json: {
              "errcode": "M_TOO_LARGE",
              "error": "Content is too large to thumbnail"
            }
          schema:
            "$ref": "definitions/errors/error.yaml"
        429:
          description: This request was rate-limited.
          schema:
            "$ref": "definitions/errors/rate_limited.yaml"
      tags:
        - Media
  "/preview_url":
    get:
      summary: "Get information about a URL for a client"
      description: |-
        Get information about a URL for the client. Typically this is called when a
        client sees a URL in a message and wants to render a preview for the user.

        .. Note::
          Clients should consider avoiding this endpoint for URLs posted in encrypted
          rooms. Encrypted rooms often contain more sensitive information the users
          do not want to share with the homeserver, and this can mean that the URLs
          being shared should also not be shared with the homeserver.

      operationId: getUrlPreview
      produces: ["application/json"]
      security:
        - accessToken: []
      parameters:
        - in: query
          type: string
          x-example: "https://matrix.org"
          name: url
          description: "The URL to get a preview of."
          required: true
        - in: query
          type: integer
          format: int64
          x-example: 1510610716656
          name: ts
          description: |-
            The preferred point in time to return a preview for. The server may
            return a newer version if it does not have the requested version
            available.
      responses:
        200:
          description: |-
            The OpenGraph data for the URL, which may be empty. Some values are
            replaced with matrix equivalents if they are provided in the response.
            The differences from the OpenGraph protocol are described here.
          schema:
            type: object
            properties:
              "matrix:image:size":
                type: integer
                format: int64
                description: |-
                  The byte-size of the image. Omitted if there is no image attached.
              "og:image":
                type: string
                description: |-
                  An `MXC URI`_ to the image. Omitted if there is no image.
          examples:
            application/json: {
                "og:title": "Matrix Blog Post",
                "og:description": "This is a really cool blog post from matrix.org",
                "og:image": "mxc://example.com/ascERGshawAWawugaAcauga",
                "og:image:type": "image/png",
                "og:image:height": 48,
                "og:image:width": 48,
                "matrix:image:size": 102400
              }
        429:
          description: This request was rate-limited.
          schema:
            "$ref": "definitions/errors/rate_limited.yaml"
      tags:
        - Media
  "/config":
    get:
      summary: Get the configuration for the content repository.
      description: |-
        This endpoint allows clients to retrieve the configuration of the content
        repository, such as upload limitations.
        Clients SHOULD use this as a guide when using content repository endpoints.
        All values are intentionally left optional. Clients SHOULD follow
        the advice given in the field description when the field is not available.

        **NOTE:** Both clients and server administrators should be aware that proxies
        between the client and the server may affect the apparent behaviour of content
        repository APIs, for example, proxies may enforce a lower upload size limit
        than is advertised by the server on this endpoint.
      operationId: getConfig
      produces: ["application/json"]
      security:
        - accessToken: []
      responses:
        200:
          description: The public content repository configuration for the matrix server.
          schema:
            type: object
            properties:
              m.upload.size:
                type: integer
                format: int64
                description: |-
                  The maximum size an upload can be in bytes.
                  Clients SHOULD use this as a guide when uploading content.
                  If not listed or null, the size limit should be treated as unknown.
          examples:
            application/json: {
               "m.upload.size": 50000000
            }
        429:
          description: This request was rate-limited.
          schema:
            "$ref": "definitions/errors/error.yaml"

      tags:
        - Media
