openapi: 3.0.3
tags:
  - name: healthcheck
  - name: token
  - name: maintenance
  - name: admins
  - name: API keys
  - name: connections
  - name: defender
  - name: quota
  - name: folders
  - name: groups
  - name: users
  - name: data retention
  - name: events
  - name: metadata
  - name: user APIs
  - name: public shares
info:
  title: SFTPGo
  description: |
    SFTPGo allows you to securely share your files over SFTP and optionally over HTTP/S, FTP/S and WebDAV as well.
    Several storage backends are supported and they are configurable per-user, so you can serve a local directory for a user and an S3 bucket (or part of it) for another one.
    SFTPGo also supports virtual folders, a virtual folder can use any of the supported storage backends. So you can have, for example, an S3 user that exposes a Google Cloud Storage bucket (or part of it) on a specified path and an encrypted local filesystem on another one.
    Virtual folders can be private or shared among multiple users, for shared virtual folders you can define different quota limits for each user.
    SFTPGo supports groups to simplify the administration of multiple accounts by letting you assign settings once to a group, instead of multiple times to each individual user.
    The SFTPGo WebClient allows end users to change their credentials, browse and manage their files in the browser and setup two-factor authentication which works with Authy, Google Authenticator and other compatible apps.
    From the WebClient each authorized user can also create HTTP/S links to externally share files and folders securely, by setting limits to the number of downloads/uploads, protecting the share with a password, limiting access by source IP address, setting an automatic expiration date.
  version: 2.2.3-dev
  contact:
    name: API support
    url: 'https://github.com/drakkan/sftpgo'
  license:
    name: AGPLv3
    url: 'https://www.gnu.org/licenses/agpl-3.0.en.html'
servers:
  - url: /api/v2
security:
  - BearerAuth: []
  - APIKeyAuth: []
paths:
  /healthz:
    get:
      security: []
      servers:
        - url: /
      tags:
        - healthcheck
      summary: health check
      description: This endpoint can be used to check if the application is running and responding to requests
      operationId: healthz
      responses:
        '200':
          description: successful operation
          content:
            text/plain:
              schema:
                type: string
                example: ok
  /shares/{id}:
    parameters:
      - name: id
        in: path
        description: the share id
        required: true
        schema:
          type: string
    get:
      security:
        - BasicAuth: []
      tags:
        - public shares
      summary: Download shared files and folders as a single zip file
      description: A zip file, containing the shared files and folders, will be generated on the fly and returned as response body. Only folders and regular files will be included in the zip. The share must be defined with the read scope and the associated user must have list and download permissions
      operationId: get_share
      parameters:
        - in: query
          name: compress
          schema:
            type: boolean
            default: true
          required: false
      responses:
        '200':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      security:
        - BasicAuth: []
      tags:
        - public shares
      summary: Upload one or more files to the shared path
      description: The share must be defined with the write scope and the associated user must have the upload permission
      operationId: upload_to_share
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                filenames:
                  type: array
                  items:
                    type: string
                    format: binary
                  minItems: 1
                  uniqueItems: true
        required: true
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '413':
          $ref: '#/components/responses/RequestEntityTooLarge'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /shares/{id}/files:
    parameters:
      - name: id
        in: path
        description: the share id
        required: true
        schema:
          type: string
    get:
      security:
        - BasicAuth: []
      tags:
        - public shares
      summary: Download a single file
      description: Returns the file contents as response body. The share must have exactly one path defined and it must be a directory for this to work
      operationId: download_share_file
      parameters:
        - in: query
          name: path
          required: true
          description: Path to the file to download. It must be URL encoded, for example the path "my dir/àdir/file.txt" must be sent as "my%20dir%2F%C3%A0dir%2Ffile.txt"
          schema:
            type: string
        - in: query
          name: inline
          required: false
          description: 'If set, the response will not have the Content-Disposition header set to `attachment`'
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '206':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /shares/{id}/dirs:
    parameters:
      - name: id
        in: path
        description: the share id
        required: true
        schema:
          type: string
    get:
      security:
        - BasicAuth: []
      tags:
        - public shares
      summary: Read directory contents
      description: Returns the contents of the specified directory for the specified share. The share must have exactly one path defined and it must be a directory for this to work
      operationId: get_share_dir_contents
      parameters:
        - in: query
          name: path
          description: Path to the folder to read. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir". If empty or missing the user's start directory is assumed. If relative, the user's start directory is used as the base
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DirEntry'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /shares/{id}/{fileName}:
    parameters:
      - name: id
        in: path
        description: the share id
        required: true
        schema:
          type: string
      - name: fileName
        in: path
        description: the name of the new file. It must be path encoded. Sub directories are not accepted
        required: true
        schema:
          type: string
      - name: X-SFTPGO-MTIME
        in: header
        schema:
          type: integer
        description: File modification time as unix timestamp in milliseconds
    post:
      security:
        - BasicAuth: []
      tags:
        - public shares
      summary: Upload a single file to the shared path
      description: The share must be defined with the write scope and the associated user must have the upload/overwrite permissions
      operationId: upload_single_to_share
      requestBody:
        content:
          application/*:
            schema:
              type: string
              format: binary
          text/*:
            schema:
              type: string
              format: binary
          image/*:
            schema:
              type: string
              format: binary
          audio/*:
            schema:
              type: string
              format: binary
          video/*:
            schema:
              type: string
              format: binary
        required: true
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '413':
          $ref: '#/components/responses/RequestEntityTooLarge'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /token:
    get:
      security:
        - BasicAuth: []
      tags:
        - token
      summary: Get a new admin access token
      description: Returns an access token and its expiration
      operationId: get_token
      parameters:
        - in: header
          name: X-SFTPGO-OTP
          schema:
            type: string
          required: false
          description: 'If you have 2FA configured for the admin attempting to log in you need to set the authentication code using this header parameter'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /logout:
    get:
      security:
        - BearerAuth: []
      tags:
        - token
      summary: Invalidate an admin access token
      description: Allows to invalidate an admin token before its expiration
      operationId: logout
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/token:
    get:
      security:
        - BasicAuth: []
      tags:
        - token
      summary: Get a new user access token
      description: Returns an access token and its expiration
      operationId: get_user_token
      parameters:
        - in: header
          name: X-SFTPGO-OTP
          schema:
            type: string
          required: false
          description: 'If you have 2FA configured, for the HTTP protocol, for the user attempting to log in you need to set the authentication code using this header parameter'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/logout:
    get:
      security:
        - BearerAuth: []
      tags:
        - token
      summary: Invalidate a user access token
      description: Allows to invalidate a client token before its expiration
      operationId: client_logout
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /version:
    get:
      tags:
        - maintenance
      summary: Get version details
      description: 'Returns version details such as the version number, build date, commit hash and enabled features'
      operationId: get_version
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VersionInfo'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /changepwd/admin:
    put:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Change admin password
      description: Changes the password for the logged in admin. Please use '/admin/changepwd' instead
      operationId: change_admin_password_deprecated
      deprecated: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PwdChange'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/changepwd:
    put:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Change admin password
      description: Changes the password for the logged in admin
      operationId: change_admin_password
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PwdChange'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/profile:
    get:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Get admin profile
      description: 'Returns the profile for the logged in admin'
      operationId: get_admin_profile
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminProfile'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Update admin profile
      description: 'Allows to update the profile for the logged in admin'
      operationId: update_admin_profile
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminProfile'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/2fa/recoverycodes:
    get:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Get recovery codes
      description: 'Returns the recovery codes for the logged in admin. Recovery codes can be used if the admin loses access to their second factor auth device. Recovery codes are returned unencrypted'
      operationId: get_admin_recovery_codes
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RecoveryCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Generate recovery codes
      description: 'Generates new recovery codes for the logged in admin. Generating new recovery codes you automatically invalidate old ones'
      operationId: generate_admin_recovery_codes
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/totp/configs:
    get:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Get available TOTP configuration
      description: Returns the available TOTP configurations for the logged in admin
      operationId: get_admin_totp_configs
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TOTPConfig'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/totp/generate:
    post:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Generate a new TOTP secret
      description: 'Generates a new TOTP secret, including the QR code as png, using the specified configuration for the logged in admin'
      operationId: generate_admin_totp_secret
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                config_name:
                  type: string
                  description: 'name of the configuration to use to generate the secret'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  config_name:
                    type: string
                  issuer:
                    type: string
                  secret:
                    type: string
                  qr_code:
                    type: string
                    format: byte
                    description: 'QR code png encoded as BASE64'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/totp/validate:
    post:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Validate a one time authentication code
      description: 'Checks if the given authentication code can be validated using the specified secret and config name'
      operationId: validate_admin_totp_secret
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                config_name:
                  type: string
                  description: 'name of the configuration to use to validate the passcode'
                passcode:
                  type: string
                  description: 'passcode to validate'
                secret:
                  type: string
                  description: 'secret to use to validate the passcode'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Passcode successfully validated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admin/totp/save:
    post:
      security:
        - BearerAuth: []
      tags:
        - admins
      summary: Save a TOTP config
      description: 'Saves the specified TOTP config for the logged in admin'
      operationId: save_admin_totp_config
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminTOTPConfig'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: TOTP configuration saved
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /connections:
    get:
      tags:
        - connections
      summary: Get connections details
      description: Returns the active users and info about their current uploads/downloads
      operationId: get_connections
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ConnectionStatus'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/connections/{connectionID}':
    delete:
      tags:
        - connections
      summary: Close connection
      description: Terminates an active connection
      operationId: close_connection
      parameters:
        - name: connectionID
          in: path
          description: ID of the connection to close
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Connection closed
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /defender/hosts:
    get:
      tags:
        - defender
      summary: Get hosts
      description: Returns hosts that are banned or for which some violations have been detected
      operationId: get_defender_hosts
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DefenderEntry'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /defender/hosts/{id}:
    parameters:
      - name: id
        in: path
        description: host id
        required: true
        schema:
          type: string
    get:
      tags:
        - defender
      summary: Get host by id
      description: Returns the host with the given id, if it exists
      operationId: get_defender_host_by_id
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefenderEntry'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - defender
      summary: Removes a host from the defender lists
      description: Unbans the specified host or clears its violations
      operationId: delete_defender_host_by_id
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /defender/bantime:
    get:
      deprecated: true
      tags:
        - defender
      summary: Get ban time
      description: Deprecated, please use '/defender/hosts', '/defender/hosts/{id}' instead
      operationId: get_ban_time
      parameters:
        - in: query
          name: ip
          required: true
          description: IPv4/IPv6 address
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BanStatus'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /defender/unban:
    post:
      deprecated: true
      tags:
        - defender
      summary: Unban
      description: Deprecated, please use '/defender/hosts/{id}' instead
      operationId: unban_host
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ip:
                  type: string
                  description: IPv4/IPv6 address to remove
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /defender/score:
    get:
      deprecated: true
      tags:
        - defender
      summary: Get score
      description: Deprecated, please use '/defender/hosts', '/defender/hosts/{id}' instead
      operationId: get_score
      parameters:
        - in: query
          name: ip
          required: true
          description: IPv4/IPv6 address
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScoreStatus'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /metadata/users/checks:
    get:
      tags:
        - metadata
      summary: Get metadata checks
      description: Returns the active metadata checks
      operationId: get_users_metadata_checks
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MetadataCheck'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /metadata/users/{username}/check:
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
    post:
      tags:
        - metadata
      summary: Start a metadata check
      description: 'Starts a new metadata check for the given user. A metadata check requires a metadata plugin and removes the metadata associated to missing items (for example objects deleted outside SFTPGo). If a metadata check for this user is already active a 409 status code is returned. Metadata are stored for cloud storage backends. This API does nothing for other backends or if no metadata plugin is configured'
      operationId: start_user_metadata_check
      responses:
        '202':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Check started
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /retention/users/checks:
    get:
      tags:
        - data retention
      summary: Get retention checks
      description: Returns the active retention checks
      operationId: get_users_retention_checks
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RetentionCheck'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /retention/users/{username}/check:
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
      - name: notifications
        in: query
        description: 'specify how to notify results'
        explode: false
        schema:
          type: array
          items:
            $ref: '#/components/schemas/RetentionCheckNotification'
    post:
      tags:
        - data retention
      summary: Start a retention check
      description: 'Starts a new retention check for the given user. If a retention check for this user is already active a 409 status code is returned'
      operationId: start_user_retention_check
      requestBody:
        required: true
        description: 'Defines virtual paths to check and their retention time in hours'
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/FolderRetention'
      responses:
        '202':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Check started
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/users/scans:
    get:
      tags:
        - quota
      summary: Get active user quota scans
      description: Returns the active user quota scans
      operationId: get_users_quota_scans
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/QuotaScan'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/users/{username}/scan:
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
    post:
      tags:
        - quota
      summary: Start a user quota scan
      description: Starts a new quota scan for the given user. A quota scan updates the number of files and their total size for the specified user and the virtual folders, if any, included in his quota
      operationId: start_user_quota_scan
      responses:
        '202':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Scan started
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/users/{username}/usage:
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
      - in: query
        name: mode
        required: false
        description: the update mode specifies if the given quota usage values should be added or replace the current ones
        schema:
          type: string
          enum:
            - add
            - reset
          description: |
            Update type:
                * `add` - add the specified quota limits to the current used ones
                * `reset` - reset the values to the specified ones. This is the default
          example: reset
    put:
      tags:
        - quota
      summary: Update disk quota usage limits
      description: Sets the current used quota limits for the given user
      operationId: user_quota_update_usage
      requestBody:
        required: true
        description: 'If used_quota_size and used_quota_files are missing they will default to 0, this means that if mode is "add" the current value, for the missing field, will remain unchanged, if mode is "reset" the missing field is set to 0'
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuotaUsage'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Quota updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/users/{username}/transfer-usage:
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
      - in: query
        name: mode
        required: false
        description: the update mode specifies if the given quota usage values should be added or replace the current ones
        schema:
          type: string
          enum:
            - add
            - reset
          description: |
            Update type:
                * `add` - add the specified quota limits to the current used ones
                * `reset` - reset the values to the specified ones. This is the default
          example: reset
    put:
      tags:
        - quota
      summary: Update transfer quota usage limits
      description: Sets the current used transfer quota limits for the given user
      operationId: user_transfer_quota_update_usage
      requestBody:
        required: true
        description: 'If used_upload_data_transfer and used_download_data_transfer are missing they will default to 0, this means that if mode is "add" the current value, for the missing field, will remain unchanged, if mode is "reset" the missing field is set to 0'
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransferQuotaUsage'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Quota updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/folders/scans:
    get:
      tags:
        - quota
      summary: Get active folder quota scans
      description: Returns the active folder quota scans
      operationId: get_folders_quota_scans
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FolderQuotaScan'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/folders/{name}/scan:
    parameters:
      - name: name
        in: path
        description: folder name
        required: true
        schema:
          type: string
    post:
      tags:
        - quota
      summary: Start a folder quota scan
      description: Starts a new quota scan for the given folder. A quota scan update the number of files and their total size for the specified folder
      operationId: start_folder_quota_scan
      responses:
        '202':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Scan started
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quotas/folders/{name}/usage:
    parameters:
      - name: name
        in: path
        description: folder name
        required: true
        schema:
          type: string
      - in: query
        name: mode
        required: false
        description: the update mode specifies if the given quota usage values should be added or replace the current ones
        schema:
          type: string
          enum:
            - add
            - reset
          description: |
            Update type:
                * `add` - add the specified quota limits to the current used ones
                * `reset` - reset the values to the specified ones. This is the default
          example: reset
    put:
      tags:
        - quota
      summary: Update folder quota usage limits
      description: Sets the current used quota limits for the given folder
      operationId: folder_quota_update_usage
      parameters:
        - in: query
          name: mode
          required: false
          description: the update mode specifies if the given quota usage values should be added or replace the current ones
          schema:
            type: string
            enum:
              - add
              - reset
            description: |
              Update type:
                * `add` - add the specified quota limits to the current used ones
                * `reset` - reset the values to the specified ones. This is the default
            example: reset
      requestBody:
        required: true
        description: 'If used_quota_size and used_quota_files are missing they will default to 0, this means that if mode is "add" the current value, for the missing field, will remain unchanged, if mode is "reset" the missing field is set to 0'
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuotaUsage'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Quota updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quota-scans:
    get:
      deprecated: true
      tags:
        - quota
      summary: Get quota scans
      description: Deprecated, please use '/quotas/users/scans' instead
      operationId: get_users_quota_scans_deprecated
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/QuotaScan'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      deprecated: true
      tags:
        - quota
      summary: Start user quota scan
      description: Deprecated, please use '/quotas/users/{username}/scan' instead
      operationId: start_user_quota_scan_deprecated
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '202':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Scan started
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /quota-update:
    put:
      deprecated: true
      tags:
        - quota
      summary: Update quota usage limits
      description: Deprecated, please use '/quotas/users/{username}/usage' instead
      operationId: user_quota_update_usage_deprecated
      parameters:
        - in: query
          name: mode
          required: false
          description: the update mode specifies if the given quota usage values should be added or replace the current ones
          schema:
            type: string
            enum:
              - add
              - reset
            description: |
              Update type:
                * `add` - add the specified quota limits to the current used ones
                * `reset` - reset the values to the specified ones. This is the default
            example: reset
      requestBody:
        required: true
        description: 'The only user mandatory fields are username, used_quota_size and used_quota_files. Please note that if the quota fields are missing they will default to 0, this means that if mode is "add" the current value will remain unchanged, if mode is "reset" the missing field is set to 0'
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Quota updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /folder-quota-update:
    put:
      deprecated: true
      tags:
        - quota
      summary: Update folder quota limits
      description: Deprecated, please use '/quotas/folders/{name}/usage' instead
      operationId: folder_quota_update_usage_deprecated
      parameters:
        - in: query
          name: mode
          required: false
          description: the update mode specifies if the given quota usage values should be added or replace the current ones
          schema:
            type: string
            enum:
              - add
              - reset
            description: |
              Update type:
                * `add` - add the specified quota limits to the current used ones
                * `reset` - reset the values to the specified ones. This is the default
            example: reset
      requestBody:
        required: true
        description: 'The only folder mandatory fields are mapped_path,used_quota_size and used_quota_files. Please note that if the used quota fields are missing they will default to 0, this means that if mode is "add" the current value will remain unchanged, if mode is "reset" the missing field is set to 0'
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BaseVirtualFolder'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Quota updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /folder-quota-scans:
    get:
      deprecated: true
      tags:
        - quota
      summary: Get folders quota scans
      description: Deprecated, please use '/quotas/folders/scans' instead
      operationId: get_folders_quota_scans_deprecated
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FolderQuotaScan'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      deprecated: true
      tags:
        - quota
      summary: Start a folder quota scan
      description: Deprecated, please use '/quotas/folders/{name}/scan' instead
      operationId: start_folder_quota_scan_deprecated
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BaseVirtualFolder'
      responses:
        '202':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Scan started
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /folders:
    get:
      tags:
        - folders
      summary: Get folders
      description: Returns an array with one or more folders
      operationId: get_folders
      parameters:
        - in: query
          name: offset
          schema:
            type: integer
            minimum: 0
            default: 0
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering folders by name. Default ASC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: ASC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BaseVirtualFolder'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - folders
      summary: Add folder
      operationId: add_folder
      description: Adds a new folder. A quota scan is required to update the used files/size
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BaseVirtualFolder'
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BaseVirtualFolder'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/folders/{name}':
    parameters:
      - name: name
        in: path
        description: folder name
        required: true
        schema:
          type: string
    get:
      tags:
        - folders
      summary: Find folders by name
      description: Returns the folder with the given name if it exists.
      operationId: get_folder_by_name
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BaseVirtualFolder'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      tags:
        - folders
      summary: Update folder
      description: Updates an existing folder
      operationId: update_folder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BaseVirtualFolder'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: User updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - folders
      summary: Delete folder
      description: Deletes an existing folder
      operationId: delete_folder
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: User deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /groups:
    get:
      tags:
        - groups
      summary: Get groups
      description: Returns an array with one or more groups
      operationId: get_groups
      parameters:
        - in: query
          name: offset
          schema:
            type: integer
            minimum: 0
            default: 0
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering groups by name. Default ASC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: ASC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Group'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - groups
      summary: Add group
      operationId: add_group
      description: Adds a new group
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Group'
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/groups/{name}':
    parameters:
      - name: name
        in: path
        description: group name
        required: true
        schema:
          type: string
    get:
      tags:
        - groups
      summary: Find groups by name
      description: Returns the group with the given name if it exists.
      operationId: get_group_by_name
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      tags:
        - groups
      summary: Update group
      description: Updates an existing group
      operationId: update_group
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Group'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: User updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - groups
      summary: Delete
      description: Deletes an existing group
      operationId: delete_group
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: User deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /events/fs:
    get:
      tags:
        - events
      summary: Get filesystem events
      description: 'Returns an array with one or more filesystem events applying the specified filters. This API is only available if you configure an "eventsearcher" plugin'
      operationId: get_fs_events
      parameters:
        - in: query
          name: start_timestamp
          schema:
            type: integer
            format: int64
            minimum: 0
            default: 0
          required: false
          description: 'the event timestamp, unix timestamp in nanoseconds, must be greater than or equal to the specified one. 0 or missing means omit this filter'
        - in: query
          name: end_timestamp
          schema:
            type: integer
            format: int64
            minimum: 0
            default: 0
          required: false
          description: 'the event timestamp, unix timestamp in nanoseconds, must be less than or equal to the specified one. 0 or missing means omit this filter'
        - in: query
          name: actions
          schema:
            type: array
            items:
              $ref: '#/components/schemas/FsEventAction'
          description: 'the event action must be included among those specified. Empty or missing means omit this filter. Actions must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: username
          schema:
            type: string
          description: 'the event username must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: ip
          schema:
            type: string
          description: 'the event IP must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: ssh_cmd
          schema:
            type: string
          description: 'the event SSH command must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: fs_provider
          schema:
            $ref: '#/components/schemas/FsProviders'
          description: 'the event filesystem provider must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: bucket
          schema:
            type: string
          description: 'the bucket must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: endpoint
          schema:
            type: string
          description: 'the endpoint must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: protocols
          schema:
            type: array
            items:
              $ref: '#/components/schemas/EventProtocols'
          description: 'the event protocol must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: statuses
          schema:
            type: array
            items:
              $ref: '#/components/schemas/FsEventStatus'
          description: 'the event status must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: instance_ids
          schema:
            type: array
            items:
              type: string
          description: 'the event instance id must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: exclude_ids
          schema:
            type: array
            items:
              type: string
          description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 1000
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering events by timestamp. Default DESC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: DESC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FsEvent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /events/provider:
    get:
      tags:
        - events
      summary: Get provider events
      description: 'Returns an array with one or more provider events applying the specified filters. This API is only available if you configure an "eventsearcher" plugin'
      operationId: get_provider_events
      parameters:
        - in: query
          name: start_timestamp
          schema:
            type: integer
            format: int64
            minimum: 0
            default: 0
          required: false
          description: 'the event timestamp, unix timestamp in nanoseconds, must be greater than or equal to the specified one. 0 or missing means omit this filter'
        - in: query
          name: end_timestamp
          schema:
            type: integer
            format: int64
            minimum: 0
            default: 0
          required: false
          description: 'the event timestamp, unix timestamp in nanoseconds, must be less than or equal to the specified one. 0 or missing means omit this filter'
        - in: query
          name: actions
          schema:
            type: array
            items:
              $ref: '#/components/schemas/ProviderEventAction'
          description: 'the event action must be included among those specified. Empty or missing means omit this filter. Actions must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: username
          schema:
            type: string
          description: 'the event username must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: ip
          schema:
            type: string
          description: 'the event IP must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: object_name
          schema:
            type: string
          description: 'the event object name must be the same as the one specified. Empty or missing means omit this filter'
          required: false
        - in: query
          name: object_types
          schema:
            type: array
            items:
              $ref: '#/components/schemas/ProviderEventObjectType'
          description: 'the event object type must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: instance_ids
          schema:
            type: array
            items:
              type: string
          description: 'the event instance id must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: exclude_ids
          schema:
            type: array
            items:
              type: string
          description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated'
          explode: false
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 1000
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering events by timestamp. Default DESC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: DESC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ProviderEvent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /apikeys:
    get:
      security:
        - BearerAuth: []
      tags:
        - API keys
      summary: Get API keys
      description: Returns an array with one or more API keys. For security reasons hashed keys are omitted in the response
      operationId: get_api_keys
      parameters:
        - in: query
          name: offset
          schema:
            type: integer
            minimum: 0
            default: 0
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering API keys by id. Default ASC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: ASC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/APIKey'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      security:
        - BearerAuth: []
      tags:
        - API keys
      summary: Add API key
      description: Adds a new API key
      operationId: add_api_key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/APIKey'
      responses:
        '201':
          description: successful operation
          headers:
            X-Object-ID:
              schema:
                type: string
              description: ID for the new created API key
            Location:
              schema:
                type: string
              description: URL to retrieve the details for the new created API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  mesage:
                    type: string
                    example: 'API key created. This is the only time the API key is visible, please save it.'
                  key:
                    type: string
                    description: 'generated API key'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/apikeys/{id}':
    parameters:
      - name: id
        in: path
        description: the key id
        required: true
        schema:
          type: string
    get:
      security:
        - BearerAuth: []
      tags:
        - API keys
      summary: Find API key by id
      description: Returns the API key with the given id, if it exists. For security reasons the hashed key is omitted in the response
      operationId: get_api_key_by_id
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKey'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      security:
        - BearerAuth: []
      tags:
        - API keys
      summary: Update API key
      description: Updates an existing API key. You cannot update the key itself, the creation date and the last use
      operationId: update_api_key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/APIKey'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: API key updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      security:
        - BearerAuth: []
      tags:
        - API keys
      summary: Delete API key
      description: Deletes an existing API key
      operationId: delete_api_key
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Admin deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /admins:
    get:
      tags:
        - admins
      summary: Get admins
      description: Returns an array with one or more admins. For security reasons hashed passwords are omitted in the response
      operationId: get_admins
      parameters:
        - in: query
          name: offset
          schema:
            type: integer
            minimum: 0
            default: 0
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering admins by username. Default ASC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: ASC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Admin'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - admins
      summary: Add admin
      description: 'Adds a new admin. Recovery codes and TOTP configuration cannot be set using this API: each admin must use the specific APIs'
      operationId: add_admin
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Admin'
            examples:
              example-1:
                value:
                  id: 1
                  status: 0
                  username: string
                  description: string
                  password: pa$$word
                  email: user@example.com
                  permissions:
                    - '*'
                  filters:
                    allow_list:
                      - 192.0.2.0/24
                      - '2001:db8::/32'
                  additional_info: string
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Admin'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/admins/{username}':
    parameters:
      - name: username
        in: path
        description: the admin username
        required: true
        schema:
          type: string
    get:
      tags:
        - admins
      summary: Find admins by username
      description: 'Returns the admin with the given username, if it exists. For security reasons the hashed password is omitted in the response'
      operationId: get_admin_by_username
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Admin'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      tags:
        - admins
      summary: Update admin
      description: 'Updates an existing admin. Recovery codes and TOTP configuration cannot be set/updated using this API: each admin must use the specific APIs. You are not allowed to update the admin impersonated using an API key'
      operationId: update_admin
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Admin'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Admin updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - admins
      summary: Delete admin
      description: Deletes an existing admin
      operationId: delete_admin
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Admin deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/admins/{username}/2fa/disable':
    parameters:
      - name: username
        in: path
        description: the admin username
        required: true
        schema:
          type: string
    put:
      tags:
        - admins
      summary: Disable second factor authentication
      description: 'Disables second factor authentication for the given admin. This API must be used if the admin loses access to their second factor auth device and has no recovery codes'
      operationId: disable_admin_2fa
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: 2FA disabled
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/admins/{username}/forgot-password':
    parameters:
      - name: username
        in: path
        description: the admin username
        required: true
        schema:
          type: string
    post:
      security: []
      tags:
        - admins
      summary: Send a password reset code by email
      description: 'You must set up an SMTP server and the account must have a valid email address, in which case SFTPGo will send a code via email to reset the password. If the specified admin does not exist, the request will be silently ignored (a success response will be returned) to avoid disclosing existing admins'
      operationId: admin_forgot_password
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/admins/{username}/reset-password':
    parameters:
      - name: username
        in: path
        description: the admin username
        required: true
        schema:
          type: string
    post:
      security: []
      tags:
        - admins
      summary: Reset the password
      description: 'Set a new password using the code received via email'
      operationId: admin_reset_password
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                password:
                  type: string
        required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /users:
    get:
      tags:
        - users
      summary: Get users
      description: Returns an array with one or more users. For security reasons hashed passwords are omitted in the response
      operationId: get_users
      parameters:
        - in: query
          name: offset
          schema:
            type: integer
            minimum: 0
            default: 0
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering users by username. Default ASC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: ASC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - users
      summary: Add user
      description: 'Adds a new user.Recovery codes and TOTP configuration cannot be set using this API: each user must use the specific APIs'
      operationId: add_user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/users/{username}':
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
    get:
      tags:
        - users
      summary: Find users by username
      description: Returns the user with the given username if it exists. For security reasons the hashed password is omitted in the response
      operationId: get_user_by_username
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      tags:
        - users
      summary: Update user
      description: 'Updates an existing user and optionally disconnects it, if connected, to apply the new settings. Recovery codes and TOTP configuration cannot be set/updated using this API: each user must use the specific APIs'
      operationId: update_user
      parameters:
        - in: query
          name: disconnect
          schema:
            type: integer
            enum:
              - 0
              - 1
          description: |
            Disconnect:
              * `0` The user will not be disconnected and it will continue to use the old configuration until connected. This is the default
              * `1` The user will be disconnected after a successful update. It must login again and so it will be forced to use the new configuration
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: User updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - users
      summary: Delete user
      description: Deletes an existing user
      operationId: delete_user
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: User deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/users/{username}/2fa/disable':
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
    put:
      tags:
        - users
      summary: Disable second factor authentication
      description: 'Disables second factor authentication for the given user. This API must be used if the user loses access to their second factor auth device and has no recovery codes'
      operationId: disable_user_2fa
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: 2FA disabled
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/users/{username}/forgot-password':
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
    post:
      security: []
      tags:
        - users
      summary: Send a password reset code by email
      description: 'You must configure an SMTP server, the account must have a valid email address and must not have the "reset-password-disabled" restriction, in which case SFTPGo will send a code via email to reset the password. If the specified user does not exist, the request will be silently ignored (a success response will be returned) to avoid disclosing existing users'
      operationId: user_forgot_password
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/users/{username}/reset-password':
    parameters:
      - name: username
        in: path
        description: the username
        required: true
        schema:
          type: string
    post:
      security: []
      tags:
        - users
      summary: Reset the password
      description: 'Set a new password using the code received via email'
      operationId: user_reset_password
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                password:
                  type: string
        required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /status:
    get:
      tags:
        - maintenance
      summary: Get status
      description: Retrieves the status of the active services
      operationId: get_status
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServicesStatus'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /dumpdata:
    get:
      tags:
        - maintenance
      summary: Dump data
      description: 'Backups data as data provider independent JSON. The backup can be saved in a local file on the server, to avoid exposing sensitive data over the network, or returned as response body. The output of dumpdata can be used as input for loaddata'
      operationId: dumpdata
      parameters:
        - in: query
          name: output-file
          schema:
            type: string
          description: Path for the file to write the JSON serialized data to. This path is relative to the configured "backups_path". If this file already exists it will be overwritten. To return the backup as response body set `output_data` to true instead.
        - in: query
          name: output-data
          schema:
            type: integer
            enum:
              - 0
              - 1
          description: |
            output data:
              * `0` or any other value != 1, the backup will be saved to a file on the server, `output_file` is required
              * `1` the backup will be returned as response body
        - in: query
          name: indent
          schema:
            type: integer
            enum:
              - 0
              - 1
          description: |
            indent:
              * `0` no indentation. This is the default
              * `1` format the output JSON
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - $ref: '#/components/schemas/BackupData'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /loaddata:
    parameters:
      - in: query
        name: scan-quota
        schema:
          type: integer
          enum:
            - 0
            - 1
            - 2
        description: |
          Quota scan:
            * `0` no quota scan is done, the imported users/folders will have used_quota_size and used_quota_files = 0 or the existing values if they already exists. This is the default
            * `1` scan quota
            * `2` scan quota if the user has quota restrictions
          required: false
      - in: query
        name: mode
        schema:
          type: integer
          enum:
            - 0
            - 1
            - 2
        description: |
          Mode:
            * `0` New objects are added, existing ones are updated. This is the default
            * `1` New objects are added, existing ones are not modified
            * `2` New objects are added, existing ones are updated and connected users are disconnected and so forced to use the new configuration
    get:
      tags:
        - maintenance
      summary: Load data from path
      description: 'Restores SFTPGo data from a JSON backup file on the server. Objects will be restored one by one and the restore is stopped if a object cannot be added or updated, so it could happen a partial restore'
      operationId: loaddata_from_file
      parameters:
        - in: query
          name: input-file
          schema:
            type: string
          required: true
          description: Path for the file to read the JSON serialized data from. This can be an absolute path or a path relative to the configured "backups_path". The max allowed file size is 10MB
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Data restored
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - maintenance
      summary: Load data
      description: 'Restores SFTPGo data from a JSON backup. Objects will be restored one by one and the restore is stopped if a object cannot be added or updated, so it could happen a partial restore'
      operationId: loaddata_from_request_body
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BackupData'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Data restored
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/changepwd:
    put:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Change user password
      description: Changes the password for the logged in user
      operationId: change_user_password
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PwdChange'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/publickeys:
    get:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      deprecated: true
      summary: Get the user's public keys
      description: 'Returns the public keys for the logged in user. Deprecated please use "/user/profile" instead'
      operationId: get_user_public_keys
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      deprecated: true
      summary: Set the user's public keys
      description: 'Sets the public keys for the logged in user. Public keys must be in OpenSSH format. Deprecated please use "/user/profile" instead'
      operationId: set_user_public_keys
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
                description: Public key in OpenSSH format
                example: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPVILdH2u3yV5SAeE6XksD1z1vXRg0E4hJUov8ITDAZ2 user@host
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/profile:
    get:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Get user profile
      description: 'Returns the profile for the logged in user'
      operationId: get_user_profile
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserProfile'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Update user profile
      description: 'Allows to update the profile for the logged in user'
      operationId: update_user_profile
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserProfile'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/2fa/recoverycodes:
    get:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Get recovery codes
      description: 'Returns the recovery codes for the logged in user. Recovery codes can be used if the user loses access to their second factor auth device. Recovery codes are returned unencrypted'
      operationId: get_user_recovery_codes
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RecoveryCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Generate recovery codes
      description: 'Generates new recovery codes for the logged in user. Generating new recovery codes you automatically invalidate old ones'
      operationId: generate_user_recovery_codes
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/totp/configs:
    get:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Get available TOTP configuration
      description: Returns the available TOTP configurations for the logged in user
      operationId: get_user_totp_configs
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TOTPConfig'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/totp/generate:
    post:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Generate a new TOTP secret
      description: 'Generates a new TOTP secret, including the QR code as png, using the specified configuration for the logged in user'
      operationId: generate_user_totp_secret
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                config_name:
                  type: string
                  description: 'name of the configuration to use to generate the secret'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  config_name:
                    type: string
                  issuer:
                    type: string
                  secret:
                    type: string
                  qr_code:
                    type: string
                    format: byte
                    description: 'QR code png encoded as BASE64'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/totp/validate:
    post:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Validate a one time authentication code
      description: 'Checks if the given authentication code can be validated using the specified secret and config name'
      operationId: validate_user_totp_secret
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                config_name:
                  type: string
                  description: 'name of the configuration to use to validate the passcode'
                passcode:
                  type: string
                  description: 'passcode to validate'
                secret:
                  type: string
                  description: 'secret to use to validate the passcode'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Passcode successfully validated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/totp/save:
    post:
      security:
        - BearerAuth: []
      tags:
        - user APIs
      summary: Save a TOTP config
      description: 'Saves the specified TOTP config for the logged in user'
      operationId: save_user_totp_config
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserTOTPConfig'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: TOTP configuration saved
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/shares:
    get:
      tags:
        - user APIs
      summary: List user shares
      description: Returns the share for the logged in user
      operationId: get_user_shares
      parameters:
        - in: query
          name: offset
          schema:
            type: integer
            minimum: 0
            default: 0
          required: false
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          required: false
          description: 'The maximum number of items to return. Max value is 500, default is 100'
        - in: query
          name: order
          required: false
          description: Ordering shares by ID. Default ASC
          schema:
            type: string
            enum:
              - ASC
              - DESC
            example: ASC
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Share'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - user APIs
      summary: Add a share
      operationId: add_share
      description: 'Adds a new share. The share id will be auto-generated'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Share'
      responses:
        '201':
          description: successful operation
          headers:
            X-Object-ID:
              schema:
                type: string
              description: ID for the new created share
            Location:
              schema:
                type: string
              description: URL to retrieve the details for the new created share
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  '/user/shares/{id}':
    parameters:
      - name: id
        in: path
        description: the share id
        required: true
        schema:
          type: string
    get:
      tags:
        - user APIs
      summary: Get share by id
      description: Returns a share by id for the logged in user
      operationId: get_user_share_by_id
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Share'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    put:
      tags:
        - user APIs
      summary: Update share
      description: 'Updates an existing share belonging to the logged in user'
      operationId: update_user_share
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Share'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Share updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - user APIs
      summary: Delete share
      description: 'Deletes an existing share belonging to the logged in user'
      operationId: delete_user_share
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: Share deleted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/folder:
    get:
      tags:
        - user APIs
      summary: Read folders contents
      description: Returns the contents of the specified folder for the logged in user. Please use '/user/dirs' instead
      operationId: get_user_folder_contents
      deprecated: true
      parameters:
        - in: query
          name: path
          description: Path to the folder to read. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir". If empty or missing the user's start directory is assumed. If relative, the user's start directory is used as the base
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DirEntry'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/dirs:
    get:
      tags:
        - user APIs
      summary: Read directory contents
      description: Returns the contents of the specified directory for the logged in user
      operationId: get_user_dir_contents
      parameters:
        - in: query
          name: path
          description: Path to the folder to read. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir". If empty or missing the user's start directory is assumed. If relative, the user's start directory is used as the base
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DirEntry'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - user APIs
      summary: Create a directory
      description: Create a directory for the logged in user
      operationId: create_user_dir
      parameters:
        - in: query
          name: path
          description: Path to the folder to create. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir"
          schema:
            type: string
          required: true
        - in: query
          name: mkdir_parents
          description: Create parent directories if they do not exist?
          schema:
            type: boolean
          required: false
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    patch:
      tags:
        - user APIs
      summary: Rename a directory
      description: Rename a directory for the logged in user. The rename is allowed for empty directory or for non empty local directories, with no virtual folders inside
      operationId: rename_user_dir
      parameters:
        - in: query
          name: path
          description: Path to the folder to rename. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir"
          schema:
            type: string
          required: true
        - in: query
          name: target
          description: New name. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir"
          schema:
            type: string
          required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - user APIs
      summary: Delete a directory
      description: Delete a directory for the logged in user. Only empty directories can be deleted
      operationId: delete_user_dir
      parameters:
        - in: query
          name: path
          description: Path to the folder to delete. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir"
          schema:
            type: string
          required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/file:
    get:
      tags:
        - user APIs
      summary: Download a single file
      description: Returns the file contents as response body. Please use '/user/files' instead
      operationId: get_user_file
      deprecated: true
      parameters:
        - in: query
          name: path
          required: true
          description: Path to the file to download. It must be URL encoded, for example the path "my dir/àdir/file.txt" must be sent as "my%20dir%2F%C3%A0dir%2Ffile.txt"
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '206':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/files:
    get:
      tags:
        - user APIs
      summary: Download a single file
      description: Returns the file contents as response body
      operationId: download_user_file
      parameters:
        - in: query
          name: path
          required: true
          description: Path to the file to download. It must be URL encoded, for example the path "my dir/àdir/file.txt" must be sent as "my%20dir%2F%C3%A0dir%2Ffile.txt"
          schema:
            type: string
        - in: query
          name: inline
          required: false
          description: 'If set, the response will not have the Content-Disposition header set to `attachment`'
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '206':
          description: successful operation
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    post:
      tags:
        - user APIs
      summary: Upload files
      description: Upload one or more files for the logged in user
      operationId: create_user_files
      parameters:
        - in: query
          name: path
          description: Parent directory for the uploaded files. It must be URL encoded, for example the path "my dir/àdir" must be sent as "my%20dir%2F%C3%A0dir". If empty or missing the root path is assumed. If a file with the same name already exists, it will be overwritten
          schema:
            type: string
        - in: query
          name: mkdir_parents
          description: Create parent directories if they do not exist?
          schema:
            type: boolean
          required: false
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                filenames:
                  type: array
                  items:
                    type: string
                    format: binary
                  minItems: 1
                  uniqueItems: true
        required: true
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '413':
          $ref: '#/components/responses/RequestEntityTooLarge'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    patch:
      tags:
        - user APIs
      summary: Rename a file
      description: Rename a file for the logged in user
      operationId: rename_user_file
      parameters:
        - in: query
          name: path
          description: Path to the file to rename. It must be URL encoded
          schema:
            type: string
          required: true
        - in: query
          name: target
          description: New name. It must be URL encoded
          schema:
            type: string
          required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
        - user APIs
      summary: Delete a file
      description: Delete a file for the logged in user.
      operationId: delete_user_file
      parameters:
        - in: query
          name: path
          description: Path to the file to delete. It must be URL encoded
          schema:
            type: string
          required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/files/upload:
    post:
      tags:
        - user APIs
      summary: Upload a single file
      description: 'Upload a single file for the logged in user to an existing directory. This API does not use multipart/form-data and so no temporary files are created server side but only a single file can be uploaded as POST body'
      operationId: create_user_file
      parameters:
        - in: query
          name: path
          description: Full file path. It must be path encoded, for example the path "my dir/àdir/file.txt" must be sent as "my%20dir%2F%C3%A0dir%2Ffile.txt". The parent directory must exist. If a file with the same name already exists, it will be overwritten
          schema:
            type: string
          required: true
        - in: query
          name: mkdir_parents
          description: Create parent directories if they do not exist?
          schema:
            type: boolean
          required: false
        - in: header
          name: X-SFTPGO-MTIME
          schema:
            type: integer
          description: File modification time as unix timestamp in milliseconds
      requestBody:
        content:
          application/*:
            schema:
              type: string
              format: binary
          text/*:
            schema:
              type: string
              format: binary
          image/*:
            schema:
              type: string
              format: binary
          audio/*:
            schema:
              type: string
              format: binary
          video/*:
            schema:
              type: string
              format: binary
        required: true
      responses:
        '201':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '413':
          $ref: '#/components/responses/RequestEntityTooLarge'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/files/metadata:
    patch:
      tags:
        - user APIs
      summary: Set metadata for a file/directory
      description: 'Set supported metadata attributes for the specified file or directory'
      operationId: setprops_user_file
      parameters:
        - in: query
          name: path
          description: Full file/directory path. It must be URL encoded, for example the path "my dir/àdir/file.txt" must be sent as "my%20dir%2F%C3%A0dir%2Ffile.txt"
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                modification_time:
                  type: integer
                  description: File modification time as unix timestamp in milliseconds
        required: true
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '413':
          $ref: '#/components/responses/RequestEntityTooLarge'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/streamzip:
    post:
      tags:
        - user APIs
      summary: Download multiple files and folders as a single zip file
      description: A zip file, containing the specified files and folders, will be generated on the fly and returned as response body. Only folders and regular files will be included in the zip
      operationId: streamzip
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
                description: Absolute file or folder path
      responses:
        '200':
          description: successful operation
          content:
            'application/zip':
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
components:
  responses:
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    Conflict:
      description: Conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    RequestEntityTooLarge:
      description: Request Entity Too Large, max allowed size exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    InternalServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
    DefaultResponse:
      description: Unexpected Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiResponse'
  schemas:
    Permission:
      type: string
      enum:
        - '*'
        - list
        - download
        - upload
        - overwrite
        - delete
        - delete_files
        - delete_dirs
        - rename
        - rename_files
        - rename_dirs
        - create_dirs
        - create_symlinks
        - chmod
        - chown
        - chtimes
      description: |
        Permissions:
          * `*` - all permissions are granted
          * `list` - list items is allowed
          * `download` - download files is allowed
          * `upload` - upload files is allowed
          * `overwrite` - overwrite an existing file, while uploading, is allowed. upload permission is required to allow file overwrite
          * `delete` - delete files or directories is allowed
          * `delete_files` - delete files is allowed
          * `delete_dirs` - delete directories is allowed
          * `rename` - rename files or directories is allowed
          * `rename_files` - rename files is allowed
          * `rename_dirs` - rename directories is allowed
          * `create_dirs` - create directories is allowed
          * `create_symlinks` - create links is allowed
          * `chmod` changing file or directory permissions is allowed
          * `chown` changing file or directory owner and group is allowed
          * `chtimes` changing file or directory access and modification time is allowed
    DirPermissions:
      type: object
      additionalProperties:
        type: array
        items:
          $ref: '#/components/schemas/Permission'
        minItems: 1
      minProperties: 1
      description: 'hash map with directory as key and an array of permissions as value. Directories must be absolute paths, permissions for root directory ("/") are required'
    AdminPermissions:
      type: string
      enum:
        - '*'
        - add_users
        - edit_users
        - del_users
        - view_users
        - view_conns
        - close_conns
        - view_status
        - manage_admins
        - manage_apikeys
        - quota_scans
        - manage_system
        - manage_defender
        - view_defender
        - retention_checks
        - metadata_checks
        - view_events
      description: |
        Admin permissions:
          * `*` - all permissions are granted
          * `add_users` - add new users is allowed
          * `edit_users` - change existing users is allowed
          * `del_users` - remove users is allowed
          * `view_users` - list users is allowed
          * `view_conns` - list active connections is allowed
          * `close_conns` - close active connections is allowed
          * `view_status` - view the server status is allowed
          * `manage_admins` - manage other admins is allowed
          * `manage_apikeys` - manage API keys is allowed
          * `quota_scans` - view and start quota scans is allowed
          * `manage_system` - backups and restores are allowed
          * `manage_defender` - remove ip from the dynamic blocklist is allowed
          * `view_defender` - list the dynamic blocklist is allowed
          * `retention_checks` - view and start retention checks is allowed
          * `metadata_checks` - view and start metadata checks is allowed
          * `view_events` - view and search filesystem and provider events is allowed
    FsProviders:
      type: integer
      enum:
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
      description: |
        Filesystem providers:
          * `0` - Local filesystem
          * `1` - S3 Compatible Object Storage
          * `2` - Google Cloud Storage
          * `3` - Azure Blob Storage
          * `4` - Local filesystem encrypted
          * `5` - SFTP
    LoginMethods:
      type: string
      enum:
        - publickey
        - password
        - password-over-SSH
        - keyboard-interactive
        - publickey+password
        - publickey+keyboard-interactive
        - TLSCertificate
        - TLSCertificate+password
      description: |
        Available login methods. To enable multi-step authentication you have to allow only multi-step login methods
          * `publickey`
          * `password`, password for all the supported protocols
          * `password-over-SSH`, password over SSH protocol (SSH/SFTP/SCP)
          * `keyboard-interactive`
          * `publickey+password` - multi-step auth: public key and password
          * `publickey+keyboard-interactive` - multi-step auth: public key and keyboard interactive
          * `TLSCertificate`
          * `TLSCertificate+password` - multi-step auth: TLS client certificate and password
    SupportedProtocols:
      type: string
      enum:
        - SSH
        - FTP
        - DAV
        - HTTP
      description: |
        Protocols:
          * `SSH` - includes both SFTP and SSH commands
          * `FTP` - plain FTP and FTPES/FTPS
          * `DAV` - WebDAV over HTTP/HTTPS
          * `HTTP` - WebClient/REST API
    MFAProtocols:
      type: string
      enum:
        - SSH
        - FTP
        - HTTP
      description: |
        Protocols:
          * `SSH` - includes both SFTP and SSH commands
          * `FTP` - plain FTP and FTPES/FTPS
          * `HTTP` - WebClient/REST API
    EventProtocols:
      type: string
      enum:
        - SSH
        - SFTP
        - SCP
        - FTP
        - DAV
        - HTTP
        - HTTPShare
        - DataRetention
        - OIDC
      description: |
        Protocols:
          * `SSH` - SSH commands
          * `SFTP` - SFTP protocol
          * `FTP` - plain FTP and FTPES/FTPS
          * `DAV` - WebDAV
          * `HTTP` - WebClient/REST API
          * `HTTPShare` - the event is generated in a public share
          * `DataRetention` - the event is generated by a data retention check
          * `OIDC` - OpenID Connect
    WebClientOptions:
      type: string
      enum:
        - publickey-change-disabled
        - write-disabled
        - mfa-disabled
        - password-change-disabled
        - api-key-auth-change-disabled
        - info-change-disabled
        - shares-disabled
        - password-reset-disabled
        - shares-without-password-disabled
      description: |
        Options:
          * `publickey-change-disabled` - changing SSH public keys is not allowed
          * `write-disabled` - upload, rename, delete are not allowed even if the user has permissions for these actions
          * `mfa-disabled` - enabling multi-factor authentication is not allowed. This option cannot be set if the user has MFA already enabled
          * `password-change-disabled` - changing password is not allowed
          * `api-key-auth-change-disabled` - enabling/disabling API key authentication is not allowed
          * `info-change-disabled` - changing info such as email and description is not allowed
          * `shares-disabled` - sharing files and directories with external users is not allowed
          * `password-reset-disabled` - resetting the password is not allowed
          * `shares-without-password-disabled` - creating shares without password protection is not allowed
    RetentionCheckNotification:
      type: string
      enum:
        - Hook
        - Email
      description: |
        Options:
          * `Hook` - notify result using the defined hook. A "data_retention_hook" must be defined in your configuration file for this to work
          * `Email` - notify results by email. The admin starting the retention check must have an associated email address and the SMTP server must be configured for this to work
    APIKeyScope:
      type: integer
      enum:
        - 1
        - 2
      description: |
        Options:
          * `1` - admin scope. The API key will be used to impersonate an SFTPGo admin
          * `2` - user scope. The API key will be used to impersonate an SFTPGo user
    ShareScope:
      type: integer
      enum:
        - 1
        - 2
      description: |
        Options:
          * `1` - read scope
          * `2` - write scope
    TOTPHMacAlgo:
      type: string
      enum:
        - sha1
        - sha256
        - sha512
      description: 'Supported HMAC algorithms for Time-based one time passwords'
    UserType:
      type: string
      enum:
        - ''
        - LDAPUser
        - OSUser
      description: This is an hint for authentication plugins. It is ignored when using SFTPGo internal authentication
    FsEventStatus:
      type: integer
      enum:
        - 1
        - 2
        - 3
      description: >
        Event status:
          * `1` - no error
          * `2` - generic error
          * `3` - quota exceeded error
    FsEventAction:
      type: string
      enum:
        - download
        - pre-upload
        - upload
        - delete
        - rename
        - mkdir
        - rmdir
        - ssh_cmd
    ProviderEventAction:
      type: string
      enum:
        - add
        - update
        - delete
    ProviderEventObjectType:
      type: string
      enum:
        - user
        - admin
        - api_key
        - share
    SSHAuthentications:
      type: string
      enum:
        - publickey
        - password
        - keyboard-interactive
        - publickey+password
        - publickey+keyboard-interactive
    TLSVersions:
      type: integer
      enum:
        - 12
        - 13
      description: >
        TLS version:
          * `12` - TLS 1.2
          * `13` - TLS 1.3
    TOTPConfig:
      type: object
      properties:
        name:
          type: string
        issuer:
          type: string
        algo:
          $ref: '#/components/schemas/TOTPHMacAlgo'
    RecoveryCode:
      type: object
      properties:
        secret:
          $ref: '#/components/schemas/Secret'
        used:
          type: boolean
      description: 'Recovery codes to use if the user loses access to their second factor auth device. Each code can only be used once, you should use these codes to login and disable or reset 2FA for your account'
    BaseTOTPConfig:
      type: object
      properties:
        enabled:
          type: boolean
        config_name:
          type: string
          description: 'This name must be defined within the "totp" section of the SFTPGo configuration file. You will be unable to save a user/admin referencing a missing config_name'
        secret:
          $ref: '#/components/schemas/Secret'
    AdminTOTPConfig:
      allOf:
        - $ref: '#/components/schemas/BaseTOTPConfig'
    UserTOTPConfig:
      allOf:
        - $ref: '#/components/schemas/BaseTOTPConfig'
        - type: object
          properties:
            protocols:
              type: array
              items:
                $ref: '#/components/schemas/MFAProtocols'
              description: 'TOTP will be required for the specified protocols. SSH protocol (SFTP/SCP/SSH commands) will ask for the TOTP passcode if the client uses keyboard interactive authentication. FTP has no standard way to support two factor authentication, if you enable the FTP support, you have to add the TOTP passcode after the password. For example if your password is "password" and your one time passcode is "123456" you have to use "password123456" as password. WebDAV is not supported since each single request must be authenticated and a passcode cannot be reused.'
    PatternsFilter:
      type: object
      properties:
        path:
          type: string
          description: 'exposed virtual path, if no other specific filter is defined, the filter applies for sub directories too. For example if filters are defined for the paths "/" and "/sub" then the filters for "/" are applied for any file outside the "/sub" directory'
        allowed_patterns:
          type: array
          items:
            type: string
          description: 'list of, case insensitive, allowed shell like patterns.'
          example:
            - '*.jpg'
            - a*b?.png
        denied_patterns:
          type: array
          items:
            type: string
          description: 'list of, case insensitive, denied shell like patterns. Denied patterns are evaluated before the allowed ones'
          example:
            - '*.zip'
        deny_policy:
          type: integer
          enum:
            - 0
            - 1
          description: |
            Deny policies
              * `0` - default policy. Denied files/directories matching the filters are visible in directory listing but cannot be uploaded/downloaded/overwritten/renamed
              * `1` - deny policy hide. This policy applies the same restrictions as the default one and denied files/directories matching the filters will also be hidden in directory listing. This mode may cause performance issues for large directories
    HooksFilter:
      type: object
      properties:
        external_auth_disabled:
          type: boolean
          example: false
          description: If true, the external auth hook, if defined, will not be executed
        pre_login_disabled:
          type: boolean
          example: false
          description: If true, the pre-login hook, if defined, will not be executed
        check_password_disabled:
          type: boolean
          example: false
          description: If true, the check password hook, if defined, will not be executed
      description: User specific hook overrides
    BandwidthLimit:
      type: object
      properties:
        sources:
          type: array
          items:
            type: string
          description: 'Source networks in CIDR notation as defined in RFC 4632 and RFC 4291 for example `192.0.2.0/24` or `2001:db8::/32`. The limit applies if the defined networks contain the client IP'
        upload_bandwidth:
          type: integer
          format: int32
          description: 'Maximum upload bandwidth as KB/s, 0 means unlimited'
        download_bandwidth:
          type: integer
          format: int32
          description: 'Maximum download bandwidth as KB/s, 0 means unlimited'
    DataTransferLimit:
      type: object
      properties:
        sources:
          type: array
          items:
            type: string
          description: 'Source networks in CIDR notation as defined in RFC 4632 and RFC 4291 for example `192.0.2.0/24` or `2001:db8::/32`. The limit applies if the defined networks contain the client IP'
        upload_data_transfer:
          type: integer
          description: 'Maximum data transfer allowed for uploads as MB. 0 means no limit'
        download_data_transfer:
          type: integer
          description: 'Maximum data transfer allowed for downloads as MB. 0 means no limit'
        total_data_transfer:
          type: integer
          description: 'Maximum total data transfer as MB. 0 means unlimited. You can set a total data transfer instead of the individual values for uploads and downloads'
    BaseUserFilters:
      type: object
      properties:
        allowed_ip:
          type: array
          items:
            type: string
          description: 'only clients connecting from these IP/Mask are allowed. IP/Mask must be in CIDR notation as defined in RFC 4632 and RFC 4291, for example "192.0.2.0/24" or "2001:db8::/32"'
          example:
            - 192.0.2.0/24
            - '2001:db8::/32'
        denied_ip:
          type: array
          items:
            type: string
          description: clients connecting from these IP/Mask are not allowed. Denied rules are evaluated before allowed ones
          example:
            - 172.16.0.0/16
        denied_login_methods:
          type: array
          items:
            $ref: '#/components/schemas/LoginMethods'
          description: if null or empty any available login method is allowed
        denied_protocols:
          type: array
          items:
            $ref: '#/components/schemas/SupportedProtocols'
          description: if null or empty any available protocol is allowed
        file_patterns:
          type: array
          items:
            $ref: '#/components/schemas/PatternsFilter'
          description: 'filters based on shell like file patterns. These restrictions do not apply to files listing for performance reasons, so a denied file cannot be downloaded/overwritten/renamed but it will still be in the list of files. Please note that these restrictions can be easily bypassed'
        max_upload_file_size:
          type: integer
          format: int64
          description: 'maximum allowed size, as bytes, for a single file upload. The upload will be aborted if/when the size of the file being sent exceeds this limit. 0 means unlimited. This restriction does not apply for SSH system commands such as `git` and `rsync`'
        tls_username:
          type: string
          enum:
            - None
            - CommonName
          description: 'defines the TLS certificate field to use as username. For FTP clients it must match the name provided using the "USER" command. For WebDAV, if no username is provided, the CN will be used as username. For WebDAV clients it must match the implicit or provided username. Ignored if mutual TLS is disabled'
        hooks:
          $ref: '#/components/schemas/HooksFilter'
        disable_fs_checks:
          type: boolean
          example: false
          description: Disable checks for existence and automatic creation of home directory and virtual folders. SFTPGo requires that the user's home directory, virtual folder root, and intermediate paths to virtual folders exist to work properly. If you already know that the required directories exist, disabling these checks will speed up login. You could, for example, disable these checks after the first login
        web_client:
          type: array
          items:
            $ref: '#/components/schemas/WebClientOptions'
          description: WebClient/user REST API related configuration options
        allow_api_key_auth:
          type: boolean
          description: 'API key authentication allows to impersonate this user with an API key'
        user_type:
          $ref: '#/components/schemas/UserType'
        bandwidth_limits:
          type: array
          items:
            $ref: '#/components/schemas/BandwidthLimit'
        data_transfer_limits:
          type: array
          items:
            $ref: '#/components/schemas/DataTransferLimit'
        external_auth_cache_time:
          type: integer
          description: 'Defines the cache time, in seconds, for users authenticated using an external auth hook. 0 means no cache'
        start_directory:
          type: string
          description: 'Specifies an alternate starting directory. If not set, the default is "/". This option is supported for SFTP/SCP, FTP and HTTP (WebClient/REST API) protocols. Relative paths will use this directory as base.'
        2fa_protocols:
          type: array
          items:
            $ref: '#/components/schemas/MFAProtocols'
          description: 'Defines protocols that require two factor authentication'
      description: Additional user options
    UserFilters:
      allOf:
        - $ref: '#/components/schemas/BaseUserFilters'
        - type: object
          properties:
            totp_config:
              $ref: '#/components/schemas/UserTOTPConfig'
            recovery_codes:
              type: array
              items:
                $ref: '#/components/schemas/RecoveryCode'
    Secret:
      type: object
      properties:
        status:
          type: string
          enum:
            - Plain
            - AES-256-GCM
            - Secretbox
            - GCP
            - AWS
            - VaultTransit
            - AzureKeyVault
            - Redacted
          description: 'Set to "Plain" to add or update an existing secret, set to "Redacted" to preserve the existing value'
        payload:
          type: string
        key:
          type: string
        additional_data:
          type: string
        mode:
          type: integer
          description: 1 means encrypted using a master key
      description: The secret is encrypted before saving, so to set a new secret you must provide a payload and set the status to "Plain". The encryption key and additional data will be generated automatically. If you set the status to "Redacted" the existig secret will be preserved
    S3Config:
      type: object
      properties:
        bucket:
          type: string
          minLength: 1
        region:
          type: string
          minLength: 1
        access_key:
          type: string
        access_secret:
          $ref: '#/components/schemas/Secret'
        role_arn:
          type: string
          description: 'Optional IAM Role ARN to assume'
        endpoint:
          type: string
          description: optional endpoint
        storage_class:
          type: string
        acl:
          type: string
          description: 'The canned ACL to apply to uploaded objects. Leave empty to use the default ACL. For more information and available ACLs, see here: https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl'
        upload_part_size:
          type: integer
          description: 'the buffer size (in MB) to use for multipart uploads. The minimum allowed part size is 5MB, and if this value is set to zero, the default value (5MB) for the AWS SDK will be used. The minimum allowed value is 5.'
        upload_concurrency:
          type: integer
          description: 'the number of parts to upload in parallel. If this value is set to zero, the default value (5) will be used'
        upload_part_max_time:
          type: integer
          description: 'the maximum time allowed, in seconds, to upload a single chunk (the chunk size is defined via "upload_part_size"). 0 means no timeout'
        download_part_size:
          type: integer
          description: 'the buffer size (in MB) to use for multipart downloads. The minimum allowed part size is 5MB, and if this value is set to zero, the default value (5MB) for the AWS SDK will be used. The minimum allowed value is 5. Ignored for partial downloads'
        download_concurrency:
          type: integer
          description: 'the number of parts to download in parallel. If this value is set to zero, the default value (5) will be used. Ignored for partial downloads'
        download_part_max_time:
          type: integer
          description: 'the maximum time allowed, in seconds, to download a single chunk (the chunk size is defined via "download_part_size"). 0 means no timeout. Ignored for partial downloads.'
        force_path_style:
          type: boolean
          description: 'Set this to "true" to force the request to use path-style addressing, i.e., "http://s3.amazonaws.com/BUCKET/KEY". By default, the S3 client will use virtual hosted bucket addressing when possible ("http://BUCKET.s3.amazonaws.com/KEY")'
        key_prefix:
          type: string
          description: 'key_prefix is similar to a chroot directory for a local filesystem. If specified the user will only see contents that starts with this prefix and so you can restrict access to a specific virtual folder. The prefix, if not empty, must not start with "/" and must end with "/". If empty the whole bucket contents will be available'
          example: folder/subfolder/
      description: S3 Compatible Object Storage configuration details
    GCSConfig:
      type: object
      properties:
        bucket:
          type: string
          minLength: 1
        credentials:
          $ref: '#/components/schemas/Secret'
        automatic_credentials:
          type: integer
          enum:
            - 0
            - 1
          description: |
            Automatic credentials:
              * `0` - disabled, explicit credentials, using a JSON credentials file, must be provided. This is the default value if the field is null
              * `1` - enabled, we try to use the Application Default Credentials (ADC) strategy to find your application's credentials
        storage_class:
          type: string
        acl:
          type: string
          description: 'The ACL to apply to uploaded objects. Leave empty to use the default ACL. For more information and available ACLs, refer to the JSON API here: https://cloud.google.com/storage/docs/access-control/lists#predefined-acl'
        key_prefix:
          type: string
          description: 'key_prefix is similar to a chroot directory for a local filesystem. If specified the user will only see contents that starts with this prefix and so you can restrict access to a specific virtual folder. The prefix, if not empty, must not start with "/" and must end with "/". If empty the whole bucket contents will be available'
          example: folder/subfolder/
      description: 'Google Cloud Storage configuration details. The "credentials" field must be populated only when adding/updating a user. It will be always omitted, since there are sensitive data, when you search/get users'
    AzureBlobFsConfig:
      type: object
      properties:
        container:
          type: string
        account_name:
          type: string
          description: 'Storage Account Name, leave blank to use SAS URL'
        account_key:
          $ref: '#/components/schemas/Secret'
        sas_url:
          $ref: '#/components/schemas/Secret'
        endpoint:
          type: string
          description: 'optional endpoint. Default is "blob.core.windows.net". If you use the emulator the endpoint must include the protocol, for example "http://127.0.0.1:10000"'
        upload_part_size:
          type: integer
          description: 'the buffer size (in MB) to use for multipart uploads. If this value is set to zero, the default value (5MB) will be used.'
        upload_concurrency:
          type: integer
          description: 'the number of parts to upload in parallel. If this value is set to zero, the default value (5) will be used'
        download_part_size:
          type: integer
          description: 'the buffer size (in MB) to use for multipart downloads. If this value is set to zero, the default value (5MB) will be used.'
        download_concurrency:
          type: integer
          description: 'the number of parts to download in parallel. If this value is set to zero, the default value (5) will be used'
        access_tier:
          type: string
          enum:
            - ''
            - Archive
            - Hot
            - Cool
        key_prefix:
          type: string
          description: 'key_prefix is similar to a chroot directory for a local filesystem. If specified the user will only see contents that starts with this prefix and so you can restrict access to a specific virtual folder. The prefix, if not empty, must not start with "/" and must end with "/". If empty the whole container contents will be available'
          example: folder/subfolder/
        use_emulator:
          type: boolean
      description: Azure Blob Storage configuration details
    CryptFsConfig:
      type: object
      properties:
        passphrase:
          $ref: '#/components/schemas/Secret'
      description: Crypt filesystem configuration details
    SFTPFsConfig:
      type: object
      properties:
        endpoint:
          type: string
          description: 'remote SFTP endpoint as host:port'
        username:
          type: string
          description: you can specify a password or private key or both. In the latter case the private key will be tried first.
        password:
          $ref: '#/components/schemas/Secret'
        private_key:
          $ref: '#/components/schemas/Secret'
        fingerprints:
          type: array
          items:
            type: string
          description: 'SHA256 fingerprints to use for host key verification. If you don''t provide any fingerprint the remote host key will not be verified, this is a security risk'
        prefix:
          type: string
          description: Specifying a prefix you can restrict all operations to a given path within the remote SFTP server.
        disable_concurrent_reads:
          type: boolean
          description: Concurrent reads are safe to use and disabling them will degrade performance. Some servers automatically delete files once they are downloaded. Using concurrent reads is problematic with such servers.
        buffer_size:
          type: integer
          minimum: 0
          maximum: 16
          example: 2
          description: The size of the buffer (in MB) to use for transfers. By enabling buffering, the reads and writes, from/to the remote SFTP server, are split in multiple concurrent requests and this allows data to be transferred at a faster rate, over high latency networks, by overlapping round-trip times. With buffering enabled, resuming uploads is not supported and a file cannot be opened for both reading and writing at the same time. 0 means disabled.
    FilesystemConfig:
      type: object
      properties:
        provider:
          $ref: '#/components/schemas/FsProviders'
        s3config:
          $ref: '#/components/schemas/S3Config'
        gcsconfig:
          $ref: '#/components/schemas/GCSConfig'
        azblobconfig:
          $ref: '#/components/schemas/AzureBlobFsConfig'
        cryptconfig:
          $ref: '#/components/schemas/CryptFsConfig'
        sftpconfig:
          $ref: '#/components/schemas/SFTPFsConfig'
      description: Storage filesystem details
    BaseVirtualFolder:
      type: object
      properties:
        id:
          type: integer
          format: int32
          minimum: 1
        name:
          type: string
          description: unique name for this virtual folder
        mapped_path:
          type: string
          description: absolute filesystem path to use as virtual folder
        description:
          type: string
          description: optional description
        used_quota_size:
          type: integer
          format: int64
        used_quota_files:
          type: integer
          format: int32
        last_quota_update:
          type: integer
          format: int64
          description: Last quota update as unix timestamp in milliseconds
        users:
          type: array
          items:
            type: string
          description: list of usernames associated with this virtual folder
        filesystem:
          $ref: '#/components/schemas/FilesystemConfig'
      description: 'Defines the filesystem for the virtual folder and the used quota limits. The same folder can be shared among multiple users and each user can have different quota limits or a different virtual path.'
    VirtualFolder:
      allOf:
        - $ref: '#/components/schemas/BaseVirtualFolder'
        - type: object
          properties:
            virtual_path:
              type: string
            quota_size:
              type: integer
              format: int64
              description: 'Quota as size in bytes. 0 menas unlimited, -1 means included in user quota. Please note that quota is updated if files are added/removed via SFTPGo otherwise a quota scan or a manual quota update is needed'
            quota_files:
              type: integer
              format: int32
              description: 'Quota as number of files. 0 menas unlimited, , -1 means included in user quota. Please note that quota is updated if files are added/removed via SFTPGo otherwise a quota scan or a manual quota update is needed'
          required:
            - virtual_path
      description: 'A virtual folder is a mapping between a SFTPGo virtual path and a filesystem path outside the user home directory. The specified paths must be absolute and the virtual path cannot be "/", it must be a sub directory. The parent directory for the specified virtual path must exist. SFTPGo will try to automatically create any missing parent directory for the configured virtual folders at user login.'
    User:
      type: object
      properties:
        id:
          type: integer
          format: int32
          minimum: 1
        status:
          type: integer
          enum:
            - 0
            - 1
          description: |
            status:
              * `0` user is disabled, login is not allowed
              * `1` user is enabled
        username:
          type: string
          description: username is unique
        email:
          type: string
          format: email
        description:
          type: string
          description: 'optional description, for example the user full name'
        expiration_date:
          type: integer
          format: int64
          description: expiration date as unix timestamp in milliseconds. An expired account cannot login. 0 means no expiration
        password:
          type: string
          format: password
          description: password or public key/SSH user certificate are mandatory. If the password has no known hashing algo prefix it will be stored, by default, using bcrypt, argon2id is supported too. You can send a password hashed as bcrypt ($2a$ prefix), argon2id, pbkdf2 or unix crypt and it will be stored as is. For security reasons this field is omitted when you search/get users
        public_keys:
          type: array
          items:
            type: string
            example: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEUWwDwEWhTbF0MqAsp/oXK1HR2cElhM8oo1uVmL3ZeDKDiTm4ljMr92wfTgIGDqIoxmVqgYIkAOAhuykAVWBzc= user@host
          description: Public keys in OpenSSH format. A password or at least one public key/SSH user certificate are mandatory.
        home_dir:
          type: string
          description: path to the user home directory. The user cannot upload or download files outside this directory. SFTPGo tries to automatically create this folder if missing. Must be an absolute path
        virtual_folders:
          type: array
          items:
            $ref: '#/components/schemas/VirtualFolder'
          description: mapping between virtual SFTPGo paths and virtual folders. If one or more of the specified folders are not inside the dataprovider they will be automatically created. You have to create the folder on the filesystem yourself
        uid:
          type: integer
          format: int32
          minimum: 0
          maximum: 2147483647
          description: 'if you run SFTPGo as root user, the created files and directories will be assigned to this uid. 0 means no change, the owner will be the user that runs SFTPGo. Ignored on windows'
        gid:
          type: integer
          format: int32
          minimum: 0
          maximum: 2147483647
          description: 'if you run SFTPGo as root user, the created files and directories will be assigned to this gid. 0 means no change, the group will be the one of the user that runs SFTPGo. Ignored on windows'
        max_sessions:
          type: integer
          format: int32
          description: Limit the sessions that a user can open. 0 means unlimited
        quota_size:
          type: integer
          format: int64
          description: Quota as size in bytes. 0 menas unlimited. Please note that quota is updated if files are added/removed via SFTPGo otherwise a quota scan or a manual quota update is needed
        quota_files:
          type: integer
          format: int32
          description: Quota as number of files. 0 menas unlimited. Please note that quota is updated if files are added/removed via SFTPGo otherwise a quota scan or a manual quota update is needed
        permissions:
          type: object
          items:
            $ref: '#/components/schemas/DirPermissions'
          minItems: 1
          example:
            /:
              - '*'
            /somedir:
              - list
              - download
        used_quota_size:
          type: integer
          format: int64
        used_quota_files:
          type: integer
          format: int32
        last_quota_update:
          type: integer
          format: int64
          description: Last quota update as unix timestamp in milliseconds
        upload_bandwidth:
          type: integer
          description: 'Maximum upload bandwidth as KB/s, 0 means unlimited'
        download_bandwidth:
          type: integer
          description: 'Maximum download bandwidth as KB/s, 0 means unlimited'
        upload_data_transfer:
          type: integer
          description: 'Maximum data transfer allowed for uploads as MB. 0 means no limit'
        download_data_transfer:
          type: integer
          description: 'Maximum data transfer allowed for downloads as MB. 0 means no limit'
        total_data_transfer:
          type: integer
          description: 'Maximum total data transfer as MB. 0 means unlimited. You can set a total data transfer instead of the individual values for uploads and downloads'
        used_upload_data_transfer:
          type: integer
          description: 'Uploaded size, as bytes, since the last reset'
        used_download_data_transfer:
          type: integer
          description: 'Downloaded size, as bytes, since the last reset'
        created_at:
          type: integer
          format: int64
          description: 'creation time as unix timestamp in milliseconds. It will be 0 for users created before v2.2.0'
        updated_at:
          type: integer
          format: int64
          description: last update time as unix timestamp in milliseconds
        last_login:
          type: integer
          format: int64
          description: Last user login as unix timestamp in milliseconds. It is saved at most once every 10 minutes
        filters:
          $ref: '#/components/schemas/UserFilters'
        filesystem:
          $ref: '#/components/schemas/FilesystemConfig'
        additional_info:
          type: string
          description: Free form text field for external systems
        groups:
          type: array
          items:
            $ref: '#/components/schemas/GroupMapping'
        oidc_custom_fields:
          type: object
          additionalProperties: true
          description: 'This field is passed to the pre-login hook if custom OIDC token fields have been configured. Field values can be of any type (this is a free form object) and depend on the type of the configured OIDC token fields'
    AdminFilters:
      type: object
      properties:
        allow_list:
          type: array
          items:
            type: string
          description: 'only clients connecting from these IP/Mask are allowed. IP/Mask must be in CIDR notation as defined in RFC 4632 and RFC 4291, for example "192.0.2.0/24" or "2001:db8::/32"'
          example:
            - 192.0.2.0/24
            - '2001:db8::/32'
        allow_api_key_auth:
          type: boolean
          description: 'API key auth allows to impersonate this administrator with an API key'
        totp_config:
          $ref: '#/components/schemas/AdminTOTPConfig'
        recovery_codes:
          type: array
          items:
            $ref: '#/components/schemas/RecoveryCode'
    Admin:
      type: object
      properties:
        id:
          type: integer
          format: int32
          minimum: 1
        status:
          type: integer
          enum:
            - 0
            - 1
          description: |
            status:
              * `0` user is disabled, login is not allowed
              * `1` user is enabled
        username:
          type: string
          description: username is unique
        description:
          type: string
          description: 'optional description, for example the admin full name'
        password:
          type: string
          format: password
          description: Admin password. For security reasons this field is omitted when you search/get admins
        email:
          type: string
          format: email
        permissions:
          type: array
          items:
            $ref: '#/components/schemas/AdminPermissions'
        filters:
          $ref: '#/components/schemas/AdminFilters'
        additional_info:
          type: string
          description: Free form text field
        created_at:
          type: integer
          format: int64
          description: 'creation time as unix timestamp in milliseconds. It will be 0 for admins created before v2.2.0'
        updated_at:
          type: integer
          format: int64
          description: last update time as unix timestamp in milliseconds
        last_login:
          type: integer
          format: int64
          description: Last user login as unix timestamp in milliseconds. It is saved at most once every 10 minutes
    AdminProfile:
      type: object
      properties:
        email:
          type: string
          format: email
        description:
          type: string
        allow_api_key_auth:
          type: boolean
          description: 'If enabled, you can impersonate this admin, in REST API, using an API key. If disabled admin credentials are required for impersonation'
    UserProfile:
      type: object
      properties:
        email:
          type: string
          format: email
        description:
          type: string
        allow_api_key_auth:
          type: boolean
          description: 'If enabled, you can impersonate this user, in REST API, using an API key. If disabled user credentials are required for impersonation'
        public_keys:
          type: array
          items:
            type: string
            example: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEUWwDwEWhTbF0MqAsp/oXK1HR2cElhM8oo1uVmL3ZeDKDiTm4ljMr92wfTgIGDqIoxmVqgYIkAOAhuykAVWBzc= user@host
            description: Public keys in OpenSSH format
    APIKey:
      type: object
      properties:
        id:
          type: string
          description: unique key identifier
        name:
          type: string
          description: User friendly key name
        key:
          type: string
          format: password
          description: We store the hash of the key. This is just like a password. For security reasons this field is omitted when you search/get API keys
        scope:
          $ref: '#/components/schemas/APIKeyScope'
        created_at:
          type: integer
          format: int64
          description: creation time as unix timestamp in milliseconds
        updated_at:
          type: integer
          format: int64
          description: last update time as unix timestamp in milliseconds
        last_use_at:
          type: integer
          format: int64
          description: last use time as unix timestamp in milliseconds. It is saved at most once every 10 minutes
        expires_at:
          type: integer
          format: int64
          description: expiration time as unix timestamp in milliseconds
        description:
          type: string
          description: optional description
        user:
          type: string
          description: username associated with this API key. If empty and the scope is "user scope" the key can impersonate any user
        admin:
          type: string
          description: admin associated with this API key. If empty and the scope is "admin scope" the key can impersonate any admin
    QuotaUsage:
      type: object
      properties:
        used_quota_size:
          type: integer
          format: int64
        used_quota_files:
          type: integer
          format: int32
    TransferQuotaUsage:
      type: object
      properties:
        used_upload_data_transfer:
          type: integer
          format: int64
          description: 'The value must be specified as bytes'
        used_download_data_transfer:
          type: integer
          format: int64
          description: 'The value must be specified as bytes'
    Transfer:
      type: object
      properties:
        operation_type:
          type: string
          enum:
            - upload
            - download
          description: |
            Operations:
              * `upload`
              * `download`
        path:
          type: string
          description: file path for the upload/download
        start_time:
          type: integer
          format: int64
          description: start time as unix timestamp in milliseconds
        size:
          type: integer
          format: int64
          description: bytes transferred
    ConnectionStatus:
      type: object
      properties:
        username:
          type: string
          description: connected username
        connection_id:
          type: string
          description: unique connection identifier
        client_version:
          type: string
          description: client version
        remote_address:
          type: string
          description: Remote address for the connected client
        connection_time:
          type: integer
          format: int64
          description: connection time as unix timestamp in milliseconds
        command:
          type: string
          description: Last SSH/FTP command or WebDAV method
        last_activity:
          type: integer
          format: int64
          description: last client activity as unix timestamp in milliseconds
        protocol:
          type: string
          enum:
            - SFTP
            - SCP
            - SSH
            - FTP
            - DAV
        active_transfers:
          type: array
          items:
            $ref: '#/components/schemas/Transfer'
    FolderRetention:
      type: object
      properties:
        path:
          type: string
          description: 'exposed virtual directory path, if no other specific retention is defined, the retention applies for sub directories too. For example if retention is defined for the paths "/" and "/sub" then the retention for "/" is applied for any file outside the "/sub" directory'
          example: '/'
        retention:
          type: integer
          description: retention time in hours. All the files with a modification time older than the defined value will be deleted. 0 means exclude this path
          example: 24
        delete_empty_dirs:
          type: boolean
          description: if enabled, empty directories will be deleted
        ignore_user_permissions:
          type: boolean
          description: 'if enabled, files will be deleted even if the user does not have the delete permission. The default is "false" which means that files will be skipped if the user does not have permission to delete them. File patterns filters will always be silently ignored'
    RetentionCheck:
      type: object
      properties:
        username:
          type: string
          description: username to which the retention check refers
        folders:
          type: array
          items:
            $ref: '#/components/schemas/FolderRetention'
        start_time:
          type: integer
          format: int64
          description: check start time as unix timestamp in milliseconds
        notifications:
          type: array
          items:
            $ref: '#/components/schemas/RetentionCheckNotification'
        email:
          type: string
          format: email
          description: 'if the notification method is set to "Email", this is the e-mail address that receives the retention check report. This field is automatically set to the email address associated with the administrator starting the check'
    MetadataCheck:
      type: object
      properties:
        username:
          type: string
          description: username to which the check refers
        start_time:
          type: integer
          format: int64
          description: check start time as unix timestamp in milliseconds
    QuotaScan:
      type: object
      properties:
        username:
          type: string
          description: username to which the quota scan refers
        start_time:
          type: integer
          format: int64
          description: scan start time as unix timestamp in milliseconds
    FolderQuotaScan:
      type: object
      properties:
        name:
          type: string
          description: folder name to which the quota scan refers
        start_time:
          type: integer
          format: int64
          description: scan start time as unix timestamp in milliseconds
    DefenderEntry:
      type: object
      properties:
        id:
          type: string
        ip:
          type: string
        score:
          type: integer
          description: the score increases whenever a violation is detected, such as an attempt to log in using an incorrect password or invalid username. If the score exceeds the configured threshold, the IP is banned. Omitted for banned IPs
        ban_time:
          type: string
          format: date-time
          description: date time until the IP is banned. For already banned hosts, the ban time is increased each time a new violation is detected. Omitted if the IP is not banned
    SSHHostKey:
      type: object
      properties:
        path:
          type: string
        fingerprint:
          type: string
    SSHBinding:
      type: object
      properties:
        address:
          type: string
          description: TCP address the server listen on
        port:
          type: integer
          description: the port used for serving requests
        apply_proxy_config:
          type: boolean
          description: 'apply the proxy configuration, if any'
    WebDAVBinding:
      type: object
      properties:
        address:
          type: string
          description: TCP address the server listen on
        port:
          type: integer
          description: the port used for serving requests
        enable_https:
          type: boolean
        min_tls_version:
          $ref: '#/components/schemas/TLSVersions'
        client_auth_type:
          type: integer
          description: 1 means that client certificate authentication is required in addition to HTTP basic authentication
        tls_cipher_suites:
          type: array
          items:
            type: string
          description: 'List of supported cipher suites for TLS version 1.2. If empty  a default list of secure cipher suites is used, with a preference order based on hardware performance'
        prefix:
          type: string
          description: 'Prefix for WebDAV resources, if empty WebDAV resources will be available at the `/` URI'
        proxy_allowed:
          type: array
          items:
            type: string
          description: 'List of IP addresses and IP ranges allowed to set proxy headers'
    PassiveIPOverride:
      type: object
      properties:
        networks:
          type: array
          items:
            type: string
        ip:
          type: string
    FTPDBinding:
      type: object
      properties:
        address:
          type: string
          description: TCP address the server listen on
        port:
          type: integer
          description: the port used for serving requests
        apply_proxy_config:
          type: boolean
          description: 'apply the proxy configuration, if any'
        tls_mode:
          type: integer
          enum:
            - 0
            - 1
            - 2
          description: |
            TLS mode:
              * `0` - clear or explicit TLS
              * `1` - explicit TLS required
              * `2` - implicit TLS
        min_tls_version:
          $ref: '#/components/schemas/TLSVersions'
        force_passive_ip:
          type: string
          description: External IP address to expose for passive connections
        passive_ip_overrides:
          type: array
          items:
            $ref: '#/components/schemas/PassiveIPOverride'
        client_auth_type:
          type: integer
          description: 1 means that client certificate authentication is required in addition to FTP authentication
        tls_cipher_suites:
          type: array
          items:
            type: string
          description: 'List of supported cipher suites for TLS version 1.2. If empty  a default list of secure cipher suites is used, with a preference order based on hardware performance'
        passive_connections_security:
          type: integer
          enum:
            - 0
            - 1
          description: |
            Active connections security:
              * `0` - require matching peer IP addresses of control and data connection
              * `1` - disable any checks
        active_connections_security:
          type: integer
          enum:
            - 0
            - 1
          description: |
            Active connections security:
              * `0` - require matching peer IP addresses of control and data connection
              * `1` - disable any checks
        debug:
          type: boolean
          description: 'If enabled any FTP command will be logged'
    SSHServiceStatus:
      type: object
      properties:
        is_active:
          type: boolean
        bindings:
          type: array
          items:
            $ref: '#/components/schemas/SSHBinding'
          nullable: true
        host_keys:
          type: array
          items:
            $ref: '#/components/schemas/SSHHostKey'
          nullable: true
        ssh_commands:
          type: array
          items:
            type: string
        authentications:
          type: array
          items:
            $ref: '#/components/schemas/SSHAuthentications'
    FTPPassivePortRange:
      type: object
      properties:
        start:
          type: integer
        end:
          type: integer
    FTPServiceStatus:
      type: object
      properties:
        is_active:
          type: boolean
        bindings:
          type: array
          items:
            $ref: '#/components/schemas/FTPDBinding'
          nullable: true
        passive_port_range:
          $ref: '#/components/schemas/FTPPassivePortRange'
    WebDAVServiceStatus:
      type: object
      properties:
        is_active:
          type: boolean
        bindings:
          type: array
          items:
            $ref: '#/components/schemas/WebDAVBinding'
          nullable: true
    DataProviderStatus:
      type: object
      properties:
        is_active:
          type: boolean
        driver:
          type: string
        error:
          type: string
    MFAStatus:
      type: object
      properties:
        is_active:
          type: boolean
        totp_configs:
          type: array
          items:
            $ref: '#/components/schemas/TOTPConfig'
    ServicesStatus:
      type: object
      properties:
        ssh:
          $ref: '#/components/schemas/SSHServiceStatus'
        ftp:
          $ref: '#/components/schemas/FTPServiceStatus'
        webdav:
          $ref: '#/components/schemas/WebDAVServiceStatus'
        data_provider:
          $ref: '#/components/schemas/DataProviderStatus'
        defender:
          type: object
          properties:
            is_active:
              type: boolean
        mfa:
          $ref: '#/components/schemas/MFAStatus'
    BanStatus:
      type: object
      properties:
        date_time:
          type: string
          format: date-time
          nullable: true
          description: if null the host is not banned
    ScoreStatus:
      type: object
      properties:
        score:
          type: integer
          description: if 0 the host is not listed
    Share:
      type: object
      properties:
        id:
          type: string
          description: auto-generated unique share identifier
        name:
          type: string
        description:
          type: string
          description: optional description
        scope:
          $ref: '#/components/schemas/ShareScope'
        paths:
          type: array
          items:
            type: string
          description: 'paths to files or directories, for share scope write this array must contain exactly one directory. Paths will not be validated on save so you can also create them after creating the share'
          example:
            - '/dir1'
            - '/dir2/file.txt'
            - '/dir3/subdir'
        username:
          type: string
        created_at:
          type: integer
          format: int64
          description: 'creation time as unix timestamp in milliseconds'
        updated_at:
          type: integer
          format: int64
          description: 'last update time as unix timestamp in milliseconds'
        last_use_at:
          type: integer
          format: int64
          description: last use time as unix timestamp in milliseconds
        expires_at:
          type: integer
          format: int64
          description: 'optional share expiration, as unix timestamp in milliseconds. 0 means no expiration'
        password:
          type: string
          description: 'optional password to protect the share. The special value "[**redacted**]" means that a password has been set, you can use this value if you want to preserve the current password when you update a share'
        max_tokens:
          type: integer
          description: 'maximum allowed access tokens. 0 means no limit'
        used_tokens:
          type: integer
        allow_from:
          type: array
          items:
            type: string
          description: 'Limit the share availability to these IP/Mask. IP/Mask must be in CIDR notation as defined in RFC 4632 and RFC 4291, for example "192.0.2.0/24" or "2001:db8::/32". An empty list means no restrictions'
          example:
            - 192.0.2.0/24
            - '2001:db8::/32'
    GroupUserSettings:
      type: object
      properties:
        home_dir:
          type: string
        max_sessions:
          type: integer
          format: int32
        quota_size:
          type: integer
          format: int64
        quota_files:
          type: integer
          format: int32
        permissions:
          type: object
          items:
            $ref: '#/components/schemas/DirPermissions'
          minItems: 1
          example:
            /:
              - '*'
            /somedir:
              - list
              - download
        upload_bandwidth:
          type: integer
          description: 'Maximum upload bandwidth as KB/s'
        download_bandwidth:
          type: integer
          description: 'Maximum download bandwidth as KB/s'
        upload_data_transfer:
          type: integer
          description: 'Maximum data transfer allowed for uploads as MB'
        download_data_transfer:
          type: integer
          description: 'Maximum data transfer allowed for downloads as MB'
        total_data_transfer:
          type: integer
          description: 'Maximum total data transfer as MB'
        filters:
          $ref: '#/components/schemas/BaseUserFilters'
    Group:
      type: object
      properties:
        id:
          type: integer
          format: int32
          minimum: 1
        name:
          type: string
          description: name is unique
        description:
          type: string
          description: 'optional description'
        created_at:
          type: integer
          format: int64
          description: creation time as unix timestamp in milliseconds
        updated_at:
          type: integer
          format: int64
          description: last update time as unix timestamp in milliseconds
        user_settings:
          $ref: '#/components/schemas/GroupUserSettings'
        virtual_folders:
          type: array
          items:
            $ref: '#/components/schemas/VirtualFolder'
          description: mapping between virtual SFTPGo paths and folders
        users:
          type: array
          items:
            type: string
          description: list of usernames associated with this group
    GroupMapping:
      type: object
      properties:
        name:
          type: string
          description: group name
        type:
          enum:
            - 1
            - 2
          description: |
            Group type:
              * `1` - Primary group
              * `2` - Secondaru group
    BackupData:
      type: object
      properties:
        users:
          type: array
          items:
            $ref: '#/components/schemas/User'
        folders:
          type: array
          items:
            $ref: '#/components/schemas/BaseVirtualFolder'
        groups:
          type: array
          items:
            $ref: '#/components/schemas/Group'
        admins:
          type: array
          items:
            $ref: '#/components/schemas/Admin'
        api_keys:
          type: array
          items:
            $ref: '#/components/schemas/APIKey'
        shares:
          type: array
          items:
            $ref: '#/components/schemas/Share'
        version:
          type: integer
    PwdChange:
      type: object
      properties:
        current_password:
          type: string
        new_password:
          type: string
    DirEntry:
      type: object
      properties:
        name:
          type: string
          description: name of the file (or subdirectory) described by the entry. This name is the final element of the path (the base name), not the entire path
        size:
          type: integer
          format: int64
          description: file size, omitted for folders and non regular files
        mode:
          type: integer
          description: |
            File mode and permission bits. More details here: https://golang.org/pkg/io/fs/#FileMode.
            Let's see some examples:
            - for a directory mode&2147483648 != 0
            - for a symlink mode&134217728 != 0
            - for a regular file mode&2401763328 == 0
        last_modified:
          type: string
          format: date-time
    FsEvent:
      type: object
      properties:
        id:
          type: string
        timestamp:
          type: integer
          format: int64
          description: 'unix timestamp in nanoseconds'
        action:
          $ref: '#/components/schemas/FsEventAction'
        username:
          type: string
        fs_path:
          type: string
        fs_target_path:
          type: string
        virtual_path:
          type: string
        virtual_target_path:
          type: string
        ssh_cmd:
          type: string
        file_size:
          type: integer
          format: int64
        status:
          $ref: '#/components/schemas/FsEventStatus'
        protocol:
          $ref: '#/components/schemas/EventProtocols'
        ip:
          type: string
        session_id:
          type: string
        fs_provider:
          $ref: '#/components/schemas/FsProviders'
        bucket:
          type: string
        endpoint:
          type: string
        open_flags:
          type: string
        instance_id:
          type: string
    ProviderEvent:
      type: object
      properties:
        id:
          type: string
        timestamp:
          type: integer
          format: int64
          description: 'unix timestamp in nanoseconds'
        action:
          $ref: '#/components/schemas/ProviderEventAction'
        username:
          type: string
        ip:
          type: string
        object_type:
          $ref: '#/components/schemas/ProviderEventObjectType'
        object_name:
          type: string
        instance_id:
          type: string
    ApiResponse:
      type: object
      properties:
        message:
          type: string
          description: 'message, can be empty'
        error:
          type: string
          description: error description if any
    VersionInfo:
      type: object
      properties:
        version:
          type: string
        build_date:
          type: string
        commit_hash:
          type: string
        features:
          type: array
          items:
            type: string
          description: 'Features for the current build. Available features are `portable`, `bolt`, `mysql`, `sqlite`, `pgsql`, `s3`, `gcs`, `metrics`. If a feature is available it has a `+` prefix, otherwise a `-` prefix'
    Token:
      type: object
      properties:
        access_token:
          type: string
        expires_at:
          type: string
          format: date-time
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    APIKeyAuth:
      type: apiKey
      in: header
      name: X-SFTPGO-API-KEY
      description: 'API key to use for authentication. API key authentication is intrinsically less secure than using a short lived JWT token. You should prefer API key authentication only for machine-to-machine communications in trusted environments. If no admin/user is associated to the provided key you need to add ".username" at the end of the key. For example if your API key is "6ajKLwswLccVBGpZGv596G.ySAXc8vtp9hMiwAuaLtzof" and you want to impersonate the admin with username "myadmin" you have to use "6ajKLwswLccVBGpZGv596G.ySAXc8vtp9hMiwAuaLtzof.myadmin" as API key. When using API key authentication you cannot manage API keys, update the impersonated admin, change password or public keys for the impersonated user.'
