openapi: 3.0.1 info: title: SFTPGo description: 'SFTPGo REST API' version: 1.8.5 servers: - url: /api/v1 security: - BasicAuth: [] paths: /version: get: tags: - version summary: Get version details operationId: get_version responses: 200: description: successful operation content: application/json: schema: type: array items: $ref : '#/components/schemas/VersionInfo' 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /providerstatus: get: tags: - providerstatus summary: Get data provider status operationId: get_provider_status responses: 200: description: successful operation content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 200 message: "Alive" error: "" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Provider Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /connection: get: tags: - connections summary: Get the active users and info about their uploads/downloads operationId: get_connections responses: 200: description: successful operation content: application/json: schema: type: array items: $ref : '#/components/schemas/ConnectionStatus' 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /connection/{connectionID}: delete: tags: - connections summary: Terminate an active connection operationId: close_connection parameters: - name: connectionID in: path description: ID of the connection to close required: true schema: type: string responses: 200: description: successful operation content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 200 message: "Connection closed" error: "" 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 404: description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 404 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /quota_scan: get: tags: - quota summary: Get the active quota scans operationId: get_quota_scans responses: 200: description: successful operation content: application/json: schema: type: array items: $ref : '#/components/schemas/QuotaScan' 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" post: tags: - quota summary: start a new quota scan description: A quota scan update the number of files and their total size for the given user operationId: start_quota_scan requestBody: required: true content: application/json: schema: $ref : '#/components/schemas/User' responses: 201: description: successful operation content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 201 message: "Scan started" error: "" 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 404: description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 404 message: "" error: "Error description if any" 409: description: Another scan is already in progress for this user content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 409 message: "Another scan is already in progress" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /user: get: tags: - users summary: Returns an array with one or more users description: For security reasons hashed passwords are omitted in the response operationId: get_users parameters: - in: query name: offset schema: type: integer minimum: 0 default: 0 required: false - in: query name: limit schema: type: integer minimum: 1 maximum: 500 default: 100 required: false description: The maximum number of items to return. Max value is 500, default is 100 - in: query name: order required: false description: Ordering users by username schema: type: string enum: - ASC - DESC example: ASC - in: query name: username required: false description: Filter by username, extact match case sensitive schema: type: string responses: 200: description: successful operation content: application/json: schema: type: array items: $ref : '#/components/schemas/User' 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" post: tags: - users summary: Adds a new user operationId: add_user requestBody: required: true content: application/json: schema: $ref : '#/components/schemas/User' responses: 200: description: successful operation content: application/json: schema: $ref : '#/components/schemas/User' 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /user/{userID}: get: tags: - users summary: Find user by ID description: For security reasons the hashed password is omitted in the response operationId: get_user_by_id parameters: - name: userID in: path description: ID of the user to retrieve required: true schema: type: integer format: int32 responses: 200: description: successful operation content: application/json: schema: $ref : '#/components/schemas/User' 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 404: description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 404 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" put: tags: - users summary: Update an existing user operationId: update_user parameters: - name: userID in: path description: ID of the user to update required: true schema: type: integer format: int32 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: status: 200 message: "User updated" error: "" 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 404: description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 404 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" delete: tags: - users summary: Delete an existing user operationId: delete_user parameters: - name: userID in: path description: ID of the user to delete required: true schema: type: integer format: int32 responses: 200: description: successful operation content: application/json: schema: $ref : '#/components/schemas/ApiResponse' example: status: 200 message: "User deleted" error: "" 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 404: description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 404 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /dumpdata: get: tags: - maintenance summary: Backup SFTPGo data serializing them as JSON description: The backup is saved to a local file to avoid to expose users hashed passwords over the network. The output of dumpdata can be used as input for loaddata operationId: dumpdata parameters: - in: query name: output_file schema: type: string required: true description: Path for the file to write the JSON serialized data to. This path is relative to the configured "backups_path". If this file already exists it will be overwritten - in: query name: indent schema: type: integer enum: - 0 - 1 description: > indent: * `0` no indentation. This is the default * `1` format the output JSON responses: 200: description: successful operation content: application/json: schema: $ref : '#/components/schemas/ApiResponse' example: status: 200 message: "Data saved" error: "" 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" /loaddata: get: tags: - maintenance summary: Restore SFTPGo data from a JSON backup description: Users will be restored one by one and the restore is stopped if a user cannot be added or updated, so it could happen a partial restore operationId: loaddata parameters: - in: query name: input_file schema: type: string required: true description: Path for the file to read the JSON serialized data from. This can be an absolute path or a path relative to the configured "backups_path". The max allowed file size is 10MB - in: query name: scan_quota schema: type: integer enum: - 0 - 1 - 2 description: > Quota scan: * `0` no quota scan is done, the imported user will have used_quota_size and used_quota_file = 0. 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 description: > Mode: * `0` New users are added, existing users are updated. This is the default * `1` New users are added, existing users are not modified responses: 200: description: successful operation content: application/json: schema: $ref : '#/components/schemas/ApiResponse' example: status: 200 message: "Data restored" error: "" 400: description: Bad request content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 400 message: "" error: "Error description if any" 401: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 401 message: "" error: "Error description if any" 403: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 403 message: "" error: "Error description if any" 500: description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiResponse' example: status: 500 message: "" error: "Error description if any" components: schemas: Permission: type: string enum: - '*' - list - download - upload - overwrite - delete - rename - create_dirs - create_symlinks - chmod - chown - chtimes description: > Permissions: * `*` - all permissions are granted * `list` - list items is allowed * `download` - download files is allowed * `upload` - upload files is allowed * `overwrite` - overwrite an existing file, while uploading, is allowed. upload permission is required to allow file overwrite * `delete` - delete files or directories is allowed * `rename` - rename files or directories is allowed * `create_dirs` - create directories is allowed * `create_symlinks` - create links is allowed * `chmod` changing file or directory permissions is allowed * `chown` changing file or directory owner and group is allowed * `chtimes` changing file or directory access and modification time is allowed DirPermissions: type: object additionalProperties: type: array items: $ref: '#/components/schemas/Permission' minItems: 1 minProperties: 1 description: hash map with directory as key and an array of permissions as value. Directories must be absolute paths, permissions for root directory ("/") are required LoginMethods: type: string enum: - 'publickey' - 'password' - 'keyboard-interactive' - 'publickey+password' - 'publickey+keyboard-interactive' ExtensionsFilter: type: object properties: path: type: string description: SFTP/SCP path, if no other specific filter is defined, the filter apply for sub directories too. For example if filters are defined for the paths "/" and "/sub" then the filters for "/" are applied for any file outside the "/sub" directory allowed_extensions: type: array items: type: string nullable: true description: list of, case insensitive, allowed files extension. Shell like expansion is not supported so you have to specify `.jpg` and not `*.jpg` example: [ ".jpg", ".png" ] denied_extensions: type: array items: type: string nullable: true description: list of, case insensitive, denied files extension. Denied file extensions are evaluated before the allowed ones example: [ ".zip" ] UserFilters: type: object properties: allowed_ip: type: array items: type: string nullable: true description: only clients connecting from these IP/Mask are allowed. IP/Mask must be in CIDR notation as defined in RFC 4632 and RFC 4291, for example "192.0.2.0/24" or "2001:db8::/32" example: [ "192.0.2.0/24", "2001:db8::/32" ] denied_ip: type: array items: type: string nullable: true description: clients connecting from these IP/Mask are not allowed. Denied rules are evaluated before allowed ones example: [ "172.16.0.0/16" ] denied_login_methods: type: array items: $ref: '#/components/schemas/LoginMethods' nullable: true description: if null or empty any available login method is allowed file_extensions: type: array items: $ref: '#/components/schemas/ExtensionsFilter' nullable: true description: filters based on file extensions. These restrictions do not apply to files listing for performance reasons, so a denied file cannot be downloaded/overwritten/renamed but it will still be listed in the list of files. Please note that these restrictions can be easily bypassed description: Additional restrictions S3Config: type: object properties: bucket: type: string minLength: 1 region: type: string minLength: 1 access_key: type: string minLength: 1 access_secret: type: string minLength: 1 description: the access secret is stored encrypted (AES-256-GCM) endpoint: type: string description: optional endpoint storage_class: type: string upload_part_size: type: integer description: the buffer size (in MB) to use for multipart uploads. The minimum allowed part size is 5MB, and if this value is set to zero, the default value (5MB) for the AWS SDK will be used. The minimum allowed value is 5. upload_concurrency: type: integer description: the number of parts to upload in parallel. If this value is set to zero, the default value (2) will be used key_prefix: type: string description: key_prefix is similar to a chroot directory for a local filesystem. If specified the SFTP user will only see contents that starts with this prefix and so you can restrict access to a specific virtual folder. The prefix, if not empty, must not start with "/" and must end with "/". If empty the whole bucket contents will be available example: folder/subfolder/ required: - bucket - region nullable: true description: S3 Compatible Object Storage configuration details GCSConfig: type: object properties: bucket: type: string minLength: 1 credentials: type: string format: byte description: Google Cloud Storage JSON credentials base64 encoded. This field must be populated only when adding/updating a user. It will be always omitted, since there are sensitive data, when you search/get users. The credentials will be stored in the configured "credentials_path" automatic_credentials: type: integer nullable: true enum: - 0 - 1 description: > Automatic credentials: * `0` - disabled, explicit credentials, using a JSON credentials file, must be provided. This is the default value if the field is null * `1` - enabled, we try to use the Application Default Credentials (ADC) strategy to find your application's credentials storage_class: type: string key_prefix: type: string description: key_prefix is similar to a chroot directory for a local filesystem. If specified the SFTP user will only see contents that starts with this prefix and so you can restrict access to a specific virtual folder. The prefix, if not empty, must not start with "/" and must end with "/". If empty the whole bucket contents will be available example: folder/subfolder/ required: - bucket nullable: true description: Google Cloud Storage configuration details FilesystemConfig: type: object properties: provider: type: integer enum: - 0 - 1 - 2 description: > Providers: * `0` - local filesystem * `1` - S3 Compatible Object Storage * `2` - Google Cloud Storage s3config: $ref: '#/components/schemas/S3Config' gcsconfig: $ref: '#/components/schemas/GCSConfig' description: Storage filesystem details VirtualFolder: type: object properties: virtual_path: type: string mapped_path: type: string exclude_from_quota: type: boolean nullable: true description: This folder will be excluded from user quota required: - virtual_path - mapped_path description: A virtual folder is a mapping between a SFTP/SCP 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 expiration_date: type: integer format: int64 description: expiration date as unix timestamp in milliseconds. An expired account cannot login. 0 means no expiration password: type: string nullable: true description: password or public key/SSH user certificate are mandatory. If the password has no known hashing algo prefix it will be stored using argon2id. You can send a password hashed as bcrypt or pbkdf2 and it will be stored as is. For security reasons this field is omitted when you search/get users public_keys: type: array items: type: string nullable: true description: a password or at least one public key/SSH user certificate are mandatory. home_dir: type: string description: path to the user home directory. The user cannot upload or download files outside this directory. SFTPGo tries to automatically create this folder if missing. Must be an absolute path virtual_folders: type: array items: $ref: '#/components/schemas/VirtualFolder' nullable: true description: mapping between virtual SFTP/SCP paths and filesystem paths outside the user home directory. Supported for local filesystem only uid: type: integer format: int32 minimum: 0 maximum: 65535 description: if you run sftpgo as root user the created files and directories will be assigned to this uid. 0 means no change, the owner will be the user that runs sftpgo. Ignored on windows gid: type: integer format: int32 minimum: 0 maximum: 65535 description: if you run sftpgo as root user the created files and directories will be assigned to this gid. 0 means no change, the group will be the one of the user that runs sftpgo. Ignored on windows max_sessions: type: integer format: int32 description: Limit the sessions that a user can open. 0 means unlimited quota_size: type: integer format: int64 description: Quota as size in bytes. 0 menas unlimited. Please note that quota is updated if files are added/removed via SFTP/SCP otherwise a quota scan 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 SFTP/SCP otherwise a quota scan 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_file: type: integer format: int32 last_quota_update: type: integer format: int64 description: Last quota update as unix timestamp in milliseconds upload_bandwidth: type: integer format: int32 description: Maximum upload bandwidth as KB/s, 0 means unlimited download_bandwidth: type: integer format: int32 description: Maximum download bandwidth as KB/s, 0 means unlimited last_login: type: integer format: int64 description: Last user login as unix timestamp in milliseconds filters: $ref: '#/components/schemas/UserFilters' filesystem: $ref: '#/components/schemas/FilesystemConfig' Transfer: type: object properties: operation_type: type: string enum: - upload - download path: type: string description: file path for the upload/download start_time: type: integer format: int64 description: start time as unix timestamp in milliseconds size: type: integer format: int64 description: bytes transferred last_activity: type: integer format: int64 description: last transfer activity as unix timestamp in milliseconds 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 ssh_command: type: string description: SSH command. This is not empty for protocol SSH last_activity: type: integer format: int64 description: last client activity as unix timestamp in milliseconds protocol: type: string enum: - SFTP - SCP - SSH active_transfers: type: array items: $ref : '#/components/schemas/Transfer' QuotaScan: type: object properties: username: type: string description: username with an active scan start_time: type: integer format: int64 description: scan start time as unix timestamp in milliseconds ApiResponse: type: object properties: status: type: integer format: int32 minimum: 200 maximum: 500 example: 200 description: HTTP Status code, for example 200 OK, 400 Bad request and so on message: type: string nullable: true description: additional message if any error: type: string nullable: true description: error description if any VersionInfo: type: object properties: version: type: string build_date: type: string commit_hash: type: string securitySchemes: BasicAuth: type: http scheme: basic