openapi: 3.0.3
info:
  title: SFTPGo
  description: 'SFTPGo REST API'
  version: 2.0.0

servers:
- url: /api/v1
security:
- BasicAuth: []
paths:
  /version:
    get:
      tags:
      - version
      summary: Get version details
      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'
  /providerstatus:
    get:
      tags:
      - providerstatus
      summary: Get data provider status
      operationId: get_provider_status
      responses:
        200:
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
              example:
                message: "Alive"
        401:
          $ref: '#/components/responses/Unauthorized'
        403:
          $ref: '#/components/responses/Forbidden'
        500:
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /connection:
    get:
      tags:
      - connections
      summary: Get the active users and info about their 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'
  /connection/{connectionID}:
    delete:
      tags:
      - connections
      summary: Terminate 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'
  /quota_scan:
    get:
      tags:
      - quota
      summary: Get the active quota scans for users home directories
      operationId: get_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'
    post:
      tags:
      - quota
      summary: start a new user quota scan
      description: A quota scan update the number of files and their total size for the specified user
      operationId: start_quota_scan
      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:
      tags:
      - quota
      summary: update the user used quota limits
      description: Set the current used quota limits for the given user
      operationId: quota_update
      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
        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'
        409:
          $ref: '#/components/responses/Conflict'
        500:
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /folder_quota_update:
    put:
      tags:
      - quota
      summary: update the folder used quota limits
      description: Set the current used quota limits for the given folder
      operationId: folder_quota_update
      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
        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'
        409:
          $ref: '#/components/responses/Conflict'
        500:
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /folder_quota_scan:
    get:
      tags:
      - quota
      summary: Get the active quota scans for folders
      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'
    post:
      tags:
      - quota
      summary: start a new folder quota scan
      description: A quota scan update the number of files and their total size for the specified folder
      operationId: start_folder_quota_scan
      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'
  /folder:
    get:
      tags:
      - folders
      summary: 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 path. Default ASC
          schema:
             type: string
             enum:
                - ASC
                - DESC
             example: ASC
        - in: query
          name: folder_path
          required: false
          description: Filter by folder path, extact match case sensitive
          schema:
             type: string
      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: Adds a new folder
      operationId: add_folder
      description: a new folder with the specified mapped_path will be added. To update the used quota parameters a quota scan is needed
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref : '#/components/schemas/BaseVirtualFolder'
      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'
        500:
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
    delete:
      tags:
      - folders
      summary: Delete an existing folder
      operationId: delete_folder
      parameters:
      - name: folder_path
        in: query
        description: path to the folder to delete
        required: true
        schema:
          type: string
      responses:
        200:
          description: successful operation
          content:
            application/json:
              schema:
                $ref : '#/components/schemas/ApiResponse'
              example:
                message: "Folder 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:
    get:
      tags:
      - users
      summary: Returns an array with one or more users
      description: 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
        - in: query
          name: username
          required: false
          description: Filter by username, extact match case sensitive
          schema:
             type: string
      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: Adds a new user
      operationId: add_user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref : '#/components/schemas/User'
      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'
        500:
          $ref: '#/components/responses/InternalServerError'
        default:
          $ref: '#/components/responses/DefaultResponse'
  /user/{userID}:
    get:
      tags:
      - users
      summary: Find user by ID
      description: For security reasons the hashed password is omitted in the response
      operationId: get_user_by_id
      parameters:
      - name: userID
        in: path
        description: ID of the user to retrieve
        required: true
        schema:
          type: integer
          format: int32
      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 an existing user
      operationId: update_user
      parameters:
      - name: userID
        in: path
        description: ID of the user to update
        required: true
        schema:
          type: integer
          format: int32
      - 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 an existing user
      operationId: delete_user
      parameters:
      - name: userID
        in: path
        description: ID of the user to delete
        required: true
        schema:
          type: integer
          format: int32
      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'
  /dumpdata:
    get:
      tags:
      - maintenance
      summary: Backup SFTPGo data serializing them as JSON
      description: The backup is saved to a local file to avoid to expose users hashed passwords over the network. The output of dumpdata can be used as input for loaddata
      operationId: dumpdata
      parameters:
        - in: query
          name: output_file
          schema:
            type: string
          required: true
          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
        - 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:
                $ref : '#/components/schemas/ApiResponse'
              example:
                message: "Data 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'
  /loaddata:
    get:
      tags:
      - maintenance
      summary: Restore SFTPGo data from a JSON backup
      description: Users and folders will be restored one by one and the restore is stopped if a user/folder cannot be added or updated, so it could happen a partial restore
      operationId: loaddata
      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
        - in: query
          name: scan_quota
          schema:
            type: integer
            enum:
              - 0
              - 1
              - 2
          description: >
            Quota scan:
              * `0` no quota scan is done, the imported users 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 users are added, existing users are updated. This is the default
                * `1` New users are added, existing users are not modified
                * `2` New users are added, existing users are updated and, if connected, they are disconnected and so forced to use the new configuration
      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'
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'
    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
        - rename
        - 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
          * `rename` - rename files or 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
    LoginMethods:
      type: string
      enum:
        - 'publickey'
        - 'password'
        - 'keyboard-interactive'
        - 'publickey+password'
        - 'publickey+keyboard-interactive'
      description: >
        To enable multi-step authentication you have to allow only multi-step login methods. If password login method is denied or no password is set then FTP and WebDAV users cannot login
    SupportedProtocols:
      type: string
      enum:
        - 'SSH'
        - 'FTP'
        - 'DAV'
    ExtensionsFilter:
      type: object
      properties:
        path:
          type: string
          description: exposed SFTPGo path, if no other specific filter is defined, the filter apply 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_extensions:
          type: array
          items:
            type: string
          nullable: true
          description: list of, case insensitive, allowed files extension. Shell like expansion is not supported so you have to specify `.jpg` and not `*.jpg`
          example: [ ".jpg", ".png" ]
        denied_extensions:
          type: array
          items:
            type: string
          nullable: true
          description: list of, case insensitive, denied files extension. Denied file extensions are evaluated before the allowed ones
          example: [ ".zip" ]
    UserFilters:
      type: object
      properties:
        allowed_ip:
          type: array
          items:
            type: string
          nullable: true
          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
          nullable: true
          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'
          nullable: true
          description: if null or empty any available login method is allowed
        denied_protocols:
          type: array
          items:
            $ref: '#/components/schemas/SupportedProtocols'
          nullable: true
          description: if null or empty any available protocol is allowed
        file_extensions:
          type: array
          items:
            $ref: '#/components/schemas/ExtensionsFilter'
          nullable: true
          description: filters based on file extensions. 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 listed in the list of files. Please note that these restrictions can be easily bypassed
        max_upload_file_size:
          type: integer
          format: int64
          nullable: true
          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`
      description: Additional restrictions
    S3Config:
      type: object
      properties:
        bucket:
          type: string
          minLength: 1
        region:
          type: string
          minLength: 1
        access_key:
          type: string
          minLength: 1
        access_secret:
          type: string
          minLength: 1
          description: the access secret is stored encrypted (AES-256-GCM)
        endpoint:
          type: string
          description: optional endpoint
        storage_class:
          type: string
        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 (2) will be used
        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/
      required:
        - bucket
        - region
      nullable: true
      description: S3 Compatible Object Storage configuration details
    GCSConfig:
      type: object
      properties:
        bucket:
          type: string
          minLength: 1
        credentials:
          type: string
          format: byte
          description: Google Cloud Storage JSON credentials base64 encoded. This 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. The credentials will be stored in the configured "credentials_path"
        automatic_credentials:
          type: integer
          nullable: true
          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
        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/
      required:
        - bucket
      nullable: true
      description: Google Cloud Storage configuration details
    FilesystemConfig:
      type: object
      properties:
        provider:
          type: integer
          enum:
            - 0
            - 1
            - 2
          description: >
            Providers:
              * `0` - local filesystem
              * `1` - S3 Compatible Object Storage
              * `2` - Google Cloud Storage
        s3config:
          $ref: '#/components/schemas/S3Config'
        gcsconfig:
          $ref: '#/components/schemas/GCSConfig'
      description: Storage filesystem details
    BaseVirtualFolder:
      type: object
      properties:
        id:
          type: integer
          format: int32
          minimum: 1
        mapped_path:
          type: string
          description: absolute filesystem path to use as virtual folder. This field is unique
        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
          nullable: true
          items:
            type: string
          description: list of usernames associated with this virtual folder
      required:
        - mapped_path
      description: defines the path 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
        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
          nullable: true
          description: password or public key/SSH user certificate are mandatory. If the password has no known hashing algo prefix it will be stored using argon2id. You can send a password hashed as bcrypt or pbkdf2 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
          nullable: true
          description: 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'
          nullable: true
          description: mapping between virtual SFTPGo paths and filesystem paths outside the user home directory. Supported for local filesystem only. 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: 65535
          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: 65535
          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
          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
        last_login:
          type: integer
          format: int64
          description: Last user login as unix timestamp in milliseconds
        filters:
          $ref: '#/components/schemas/UserFilters'
        filesystem:
          $ref: '#/components/schemas/FilesystemConfig'
    Transfer:
      type: object
      properties:
        operation_type:
          type: string
          enum:
            - 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
          nullable: true
          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
          nullable: true
          description: SSH 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
          nullable: true
          items:
            $ref : '#/components/schemas/Transfer'
    QuotaScan:
      type: object
      properties:
        username:
          type: string
          description: username with an active scan
        start_time:
          type: integer
          format: int64
          description: scan start time as unix timestamp in milliseconds
    FolderQuotaScan:
      type: object
      properties:
        mapped_path:
          type: string
          description: path with an active scan
        start_time:
          type: integer
          format: int64
          description: scan start time as unix timestamp in milliseconds
    ApiResponse:
      type: object
      properties:
        message:
          type: string
          description: message, can be empty
        error:
          type: string
          nullable: true
          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
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
