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