openapi: 3.0.3 tags: - name: healthcheck - name: token - name: maintenance - name: admins - name: connections - name: defender - name: quota - name: folders - name: users info: title: SFTPGo description: SFTPGo REST API version: 2.0.3 contact: 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: [] 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 /token: get: security: - BasicAuth: [] tags: - token summary: Get a new access token description: Returns an access token and its expiration operationId: get_token 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: tags: - token summary: Invalidate description: Allows to invalidate a 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' /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: 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' /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/bantime: get: tags: - defender summary: Get ban time description: Returns the ban time for the specified IPv4/IPv6 address 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: tags: - defender summary: Unban description: Removes the specified IPv4/IPv6 from the banned ones 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: tags: - defender summary: Get score description: Returns the score for the specified IPv4/IPv6 address 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' /quota-scans: get: tags: - quota summary: Get quota scans description: Returns active user quota scans 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 user quota scan description: Starts a new quota scan for the given user. 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 user quota limits description: Sets 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 folder quota limits description: Sets 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-scans: get: tags: - quota summary: Get folders quota scans description: Returns 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 folder quota scan description: Starts a new quota scan for the given user. 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' /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 path. 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' /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 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 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' /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 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' 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' /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 users/admins are added, existing users/admins are updated. This is the default * `1` New users/admins are added, existing users/admins 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 get: tags: - maintenance summary: Load data from path description: 'Restores SFTPGo data from a JSON backup file on the server. Users, folders and admins will be restored one by one and the restore is stopped if a user/folder/admin 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. Users, folders and admins will be restored one by one and the restore is stopped if a user/folder/admin 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' 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' AdminPermissions: type: string enum: - '*' - add_users - edit_users - del_users - view_users - view_conns - close_conns - view_status - manage_admins - quota_scans - manage_system - manage_defender - view_defender LoginMethods: type: string enum: - publickey - password - keyboard-interactive - publickey+password - publickey+keyboard-interactive - TLSCertificate - TLSCertificate+password description: | To enable multi-step authentication you have to allow only multi-step login methods SupportedProtocols: type: string enum: - SSH - FTP - DAV PatternsFilter: type: object properties: path: type: string description: 'exposed virtual 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_patterns: type: array items: type: string description: 'list of, case insensitive, allowed shell like file patterns.' example: - '*.jpg' - a*b?.png denied_patterns: type: array items: type: string description: 'list of, case insensitive, denied shell like file patterns. Denied patterns are evaluated before the allowed ones' example: - '*.zip' ExtensionsFilter: type: object properties: path: type: string description: 'exposed virtual 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 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 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 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' file_extensions: type: array items: $ref: '#/components/schemas/ExtensionsFilter' description: 'filters based on shell like patterns. Deprecated, use 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' description: Additional user restrictions Secret: type: object properties: status: type: string enum: - Plain - AES-256-GCM - Secretbox - GCP - AWS - VaultTransit - 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 S3Config: type: object properties: bucket: type: string minLength: 1 region: type: string minLength: 1 access_key: type: string access_secret: $ref: '#/components/schemas/Secret' 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 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 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 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: type: string description: 'Shared access signature URL, leave blank if using account/key' 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 (4MB) 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 (2) 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. FilesystemConfig: type: object properties: provider: type: integer enum: - 0 - 1 - 2 - 3 - 4 - 5 description: | Providers: * `0` - Local filesystem * `1` - S3 Compatible Object Storage * `2` - Google Cloud Storage * `3` - Azure Blob Storage * `4` - Local filesystem encrypted * `5` - SFTP 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 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 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 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 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' 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. 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 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' 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 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 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' 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 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 client_auth_type: type: integer description: 1 means that client certificate authentication is required in addition to HTTP basic authentication 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: | * `0` - clear or explicit TLS * `1` - explicit TLS required * `2` - implicit TLS force_passive_ip: type: string description: External IP address to expose for passive connections client_auth_type: type: integer description: 1 means that client certificate authentication is required in addition to FTP authentication 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 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 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 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 BackupData: type: object properties: users: type: array items: $ref: '#/components/schemas/User' folders: type: array items: $ref: '#/components/schemas/BaseVirtualFolder' admins: type: array items: $ref: '#/components/schemas/Admin' version: type: integer PwdChange: type: object properties: current_password: type: string new_password: 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