Skip to content

File Manager

Browser file manager with ACE editor, search, upload/download, permissions, immutable lock, and Git integration.

All endpoints below are mounted under /api. Authentication: Authorization: Bearer <token> unless noted as public.

Endpoint count: 35

Endpoints

Method Path Handler Guards
POST /api/filemanager/chmod fmChmod RequirePermission(db, "websites_management")
POST /api/filemanager/compress fmCompress RequirePermission(db, "websites_management")
POST /api/filemanager/copy fmCopy RequirePermission(db, "websites_management")
POST /api/filemanager/delete fmDelete RequirePermission(db, "websites_management")
GET /api/filemanager/dirsize fmDirSize RequirePermission(db, "websites_management")
GET /api/filemanager/download fmDownload RequirePermission(db, "websites_management")
POST /api/filemanager/download-url fmDownloadUrl RequirePermission(db, "websites_management")
POST /api/filemanager/extract fmExtract RequirePermission(db, "websites_management")
GET /api/filemanager/git fmGitStatus RequirePermission(db, "websites_management")
POST /api/filemanager/git/clone fmGitClone RequirePermission(db, "websites_management")
POST /api/filemanager/git/commit fmGitCommit RequirePermission(db, "websites_management")
GET /api/filemanager/git/diff fmGitDiff RequirePermission(db, "websites_management")
POST /api/filemanager/git/init fmGitInit RequirePermission(db, "websites_management")
GET /api/filemanager/git/log fmGitLog RequirePermission(db, "websites_management")
POST /api/filemanager/git/pull fmGitPull RequirePermission(db, "websites_management")
POST /api/filemanager/git/push fmGitPush RequirePermission(db, "websites_management")
POST /api/filemanager/git/remote fmGitAddRemote RequirePermission(db, "websites_management")
POST /api/filemanager/git/revert fmGitRevert RequirePermission(db, "websites_management")
GET /api/filemanager/git/show fmGitShow RequirePermission(db, "websites_management")
GET /api/filemanager/history fmHistory RequirePermission(db, "websites_management")
GET /api/filemanager/history/all fmHistoryAll RequirePermission(db, "websites_management")
POST /api/filemanager/history/clear fmHistoryClear RequirePermission(db, "websites_management")
GET /api/filemanager/history/content fmHistoryContent RequirePermission(db, "websites_management")
GET /api/filemanager/history/download fmHistoryDownload RequirePermission(db, "websites_management")
POST /api/filemanager/history/restore fmHistoryRestore RequirePermission(db, "websites_management")
POST /api/filemanager/lock fmLock RequirePermission(db, "websites_management")
POST /api/filemanager/mkdir fmMkDir RequirePermission(db, "websites_management")
POST /api/filemanager/move fmMove RequirePermission(db, "websites_management")
GET /api/filemanager/read fmRead RequirePermission(db, "websites_management")
POST /api/filemanager/rename fmRename RequirePermission(db, "websites_management")
GET /api/filemanager/search fmSearch RequirePermission(db, "websites_management")
POST /api/filemanager/unlock fmUnlock RequirePermission(db, "websites_management")
POST /api/filemanager/upload fmUpload RequirePermission(db, "websites_management")
POST /api/filemanager/wget-upload fmWgetUpload RequirePermission(db, "websites_management")
POST /api/filemanager/write fmWrite RequirePermission(db, "websites_management")

Source

Handlers for this section live in api/routes/handlers_*.go in the StarkOne source. Each handler binds its request body with gin.ShouldBindJSON(&req) and responds with the standard envelope:

{ "data": { ... } }

On error:

{ "error": { "code": "string", "message": "string" } }

Reference

All file-manager handlers resolve the target Linux user from either a username value or a numeric website_id (looked up to its owning username). All paths are rooted at the user's home directory /home/{username}.

POST /api/filemanager/chmod

Changes the permission mode of a file or directory (optionally recursively).

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (required)",
  "mode": "string (required)",
  "recursive": "bool (optional)"
}
Field Type Required Description
website_id int no Website whose owner is the target user. Either this or username must be provided.
username string no Target Linux user. Takes precedence over website_id.
path string yes Path relative to the user home.
mode string yes Octal permission mode (e.g. "755").
recursive bool no If true, applies the mode recursively.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or neither website_id nor username resolved a user.
404 not_found website_id did not match a website.
500 chmod_failed The chmod operation failed.
500 server_error Website lookup failed.

Side effects

  • Changes file mode bits on the target path (recursively when recursive is set).

Example

curl -X POST https://panel.example.com:2087/api/filemanager/chmod \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html/index.php", "mode": "644"}'

POST /api/filemanager/compress

Compresses one or more paths into an archive in the user's home directory, auto-suffixing the name (.1, .2, …) if a file with that name already exists.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "paths": ["string (required)"],
  "archive_name": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
paths string[] yes Paths (relative to home) to include in the archive.
archive_name string yes Desired archive file name, placed in the user home.

Response - 200 OK

{ "data": { "success": true, "archive": "backup.tar.gz" } }

The archive value reflects the actual name used, which may differ from the requested name if a collision was resolved.

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 compress_failed Archive creation failed.

Side effects

  • Writes a new archive file into /home/{username}.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/compress \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "paths": ["public_html"], "archive_name": "site.tar.gz"}'

POST /api/filemanager/copy

Copies a file or directory from a source path to a destination path within the user home.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "src_path": "string (required)",
  "dst_path": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
src_path string yes Source path relative to home.
dst_path string yes Destination path relative to home.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 copy_failed Copy operation failed.

Side effects

  • Creates a copy of the source at the destination path.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/copy \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "src_path": "a.txt", "dst_path": "b.txt"}'

POST /api/filemanager/delete

Deletes one or more paths within the user home; stops at the first failure.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "paths": ["string (required)"]
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
paths string[] yes Paths (relative to home) to delete.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 delete_failed Deleting one of the paths failed.

Side effects

  • Removes the specified files/directories from disk.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/delete \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "paths": ["tmp/old.log", "tmp/cache"]}'

GET /api/filemanager/dirsize

Returns the total size of a directory.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Directory path relative to home.

Response - 200 OK

{ "data": { "size": 123456 } }

Errors

Status Code Meaning
400 bad_request No user resolved from username/website_id.
404 not_found website_id did not match a website.
500 dirsize_failed Size computation failed.

Example

curl "https://panel.example.com:2087/api/filemanager/dirsize?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN"

GET /api/filemanager/download

Streams a file as an attachment download.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes File path relative to home.

Response - 200 OK

Returns the raw file bytes with a Content-Disposition: attachment header. This endpoint does not use the JSON envelope.

Errors

Status Code Meaning
400 bad_request No user resolved, or the path is invalid / could not be resolved to an absolute path.
404 not_found website_id did not match a website.

Example

curl -OJ "https://panel.example.com:2087/api/filemanager/download?username=user1&path=public_html/index.php" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/download-url

Downloads a remote URL into the user home directory, running curl as the target user and fixing ownership afterward.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (optional)",
  "url": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
path string no Destination directory relative to home. Empty or "." means the home root.
url string yes Remote URL to download. The filename is derived from the URL (query string stripped); falls back to downloaded_file.

Response - 200 OK

{ "data": { "filename": "archive.zip", "path": "/home/user1/archive.zip", "size": "1.2 MB" } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, no user resolved, or destination path could not be resolved.
404 not_found website_id did not match a website.
500 user_error The target Linux user could not be looked up.
500 download_failed The curl download failed (partial file is removed).

Side effects

  • Runs sudo -u {username} curl -fsSL -o {dest} {url} to fetch the file.
  • Writes the downloaded file into the destination directory and chowns it to the user.
  • Removes any partial file on failure.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/download-url \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html", "url": "https://example.com/file.zip"}'

POST /api/filemanager/extract

Extracts an archive into a destination directory within the user home.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "archive_path": "string (required)",
  "dst_path": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
archive_path string yes Path to the archive relative to home.
dst_path string yes Destination directory relative to home.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 extract_failed Extraction failed.

Side effects

  • Extracts archive contents into the destination directory on disk.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/extract \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "archive_path": "site.tar.gz", "dst_path": "restore"}'

GET /api/filemanager/git

Reports Git status for the repository containing the given path (searching the path and its parents for a .git directory).

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Response - 200 OK

When no repository is found:

{ "data": { "isGit": false } }

When a repository is found:

{
  "data": {
    "isGit": true,
    "branch": "main",
    "changed": 2,
    "untracked": 1,
    "lastCommit": "a1b2c3d commit subject",
    "gitDir": "/home/user1/public_html",
    "hasRemote": true,
    "files": [ { "status": "M", "path": "index.php" } ]
  }
}

Errors

Status Code Meaning
400 bad_request No user resolved from username/website_id.
404 not_found website_id did not match a website.

Side effects

  • Runs read-only git commands (branch, status --porcelain, log -1, remote) in the repository directory.

Example

curl "https://panel.example.com:2087/api/filemanager/git?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/git/clone

Clones a remote repository into a subdirectory of the given path (named after the repo).

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Parent directory (relative to home) to clone into.

Request body

{ "url": "string (required)" }
Field Type Required Description
url string yes Repository URL to clone.

Response - 200 OK

{ "data": { "message": "Cloned to myrepo" } }

Errors

Status Code Meaning
400 bad_request No user resolved, or url missing/invalid JSON.
404 not_found website_id did not match a website.
500 git_error The git clone command failed (message contains git output).

Side effects

  • Registers the clone path as a global Git safe.directory.
  • Runs git clone {url} {path}/{repoName}, writing the repository to disk.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/clone?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://github.com/example/repo.git"}'

POST /api/filemanager/git/commit

Commits changes in the repository containing the given path, optionally staging all changes first.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Request body

{ "message": "string (required)", "all": "bool (optional)" }
Field Type Required Description
message string yes Commit message. An empty message is rejected.
all bool no If true, runs git add -A before committing.

Response - 200 OK

{ "data": { "message": "Committed: my message" } }

If there are no staged changes, returns { "data": { "message": "Nothing to commit" } }.

Errors

Status Code Meaning
400 bad_request No user resolved, or commit message missing/invalid JSON.
404 not_found website_id did not match a website.
500 git_error The git commit command failed.

Side effects

  • Optionally runs git add -A, then git commit -m, writing a new commit to the repository.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/commit?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "Update homepage", "all": true}'

GET /api/filemanager/git/diff

Returns the git diff against HEAD for the repository, optionally scoped to a single file (falling back to showing full file content for new/untracked files).

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.
file string yes Restrict the diff to this single file.

Response - 200 OK

{ "diff": "diff --git a/index.php b/index.php ..." }

This endpoint returns a bare diff key, not the standard envelope.

Errors

Status Code Meaning
400 bad_request No user resolved.
400 (none) { "error": { "message": "Not a git repository" } } when no .git directory is found.
404 not_found website_id did not match a website.

Side effects

  • Runs read-only git diff in the repository directory.

Example

curl "https://panel.example.com:2087/api/filemanager/git/diff?username=user1&path=public_html&file=index.php" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/git/init

Initializes a new Git repository at the given path (defaulting the initial branch to main).

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Directory (relative to home) to initialize.

Response - 200 OK

{ "data": { "message": "Git repository initialized" } }

Errors

Status Code Meaning
400 bad_request No user resolved.
400 already_exists A .git directory already exists at the path.
404 not_found website_id did not match a website.
500 git_error git init failed (after falling back to a plain git init).

Side effects

  • Registers the path as a global Git safe.directory.
  • Runs git init --initial-branch=main (or git init), creating a .git directory.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/init?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN"

GET /api/filemanager/git/log

Returns up to the 50 most recent commits for the repository.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Response - 200 OK

{
  "data": {
    "commits": [
      { "hash": "a1b2c3d4...", "author": "Jane Dev", "date": "2 days ago", "subject": "Initial commit" }
    ]
  }
}

Errors

Status Code Meaning
400 bad_request No user resolved.
404 not_found website_id did not match a website.
500 git_error git log failed.

Side effects

  • Runs read-only git log in the repository directory.

Example

curl "https://panel.example.com:2087/api/filemanager/git/log?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/git/pull

Runs git pull in the repository containing the given path.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Response - 200 OK

{ "data": { "message": "Already up to date." } }

Errors

Status Code Meaning
400 bad_request No user resolved.
404 not_found website_id did not match a website.
500 git_error git pull failed (message contains git output).

Side effects

  • Runs git pull, which may update working-tree files and refs.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/pull?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/git/push

Runs git push in the repository containing the given path.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Response - 200 OK

{ "data": { "message": "Push completed" } }

The message contains git output, or "Push completed" when output is empty.

Errors

Status Code Meaning
400 bad_request No user resolved.
404 not_found website_id did not match a website.
500 git_error git push failed (message contains git output).

Side effects

  • Runs git push to the configured remote.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/push?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/git/remote

Adds a Git remote to the repository, or updates its URL if a remote with that name already exists.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Request body

{ "url": "string (required)", "name": "string (optional)" }
Field Type Required Description
url string yes Remote URL.
name string no Remote name; defaults to origin.

Response - 200 OK

{ "data": { "message": "Remote 'origin' added" } }

When the remote already existed, the message is "Remote '<name>' updated".

Errors

Status Code Meaning
400 bad_request No user resolved, or url missing/invalid JSON.
404 not_found website_id did not match a website.
500 git_error Adding or updating the remote failed.

Side effects

  • Runs git remote add (or git remote set-url), modifying the repository config.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/remote?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://github.com/example/repo.git", "name": "origin"}'

POST /api/filemanager/git/revert

Reverts a specific commit (using git revert --no-commit) and then records the revert as a new commit.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.

Request body

{ "hash": "string (required)" }
Field Type Required Description
hash string yes Commit hash to revert.

Response - 200 OK

{ "data": { "message": "Reverted commit a1b2c3d" } }

Errors

Status Code Meaning
400 bad_request No user resolved, or hash missing/invalid JSON.
404 not_found website_id did not match a website.
500 git_error git revert failed.

Side effects

  • Runs git revert --no-commit {hash} then git commit, creating a new revert commit.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/git/revert?username=user1&path=public_html" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"hash": "a1b2c3d4e5f6"}'

GET /api/filemanager/git/show

Returns details (metadata, changed files, and full diff) for a single commit.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Path (relative to home) used to locate the repository.
hash string no Commit hash to show. Required (a missing hash returns 400).

Response - 200 OK

{
  "data": {
    "hash": "a1b2c3d4...",
    "author": "Jane Dev",
    "date": "2 days ago",
    "subject": "Update homepage",
    "body": "",
    "files": [ { "path": "index.php", "status": "M" } ],
    "diff": "diff --git a/index.php b/index.php ..."
  }
}

Errors

Status Code Meaning
400 bad_request No user resolved, or hash query param missing.
404 not_found website_id did not match a website.
500 git_error git show failed.

Side effects

  • Runs read-only git show commands in the repository directory.

Example

curl "https://panel.example.com:2087/api/filemanager/git/show?username=user1&path=public_html&hash=a1b2c3d" \
  -H "Authorization: Bearer $TOKEN"

GET /api/filemanager/history

Returns the saved version history for a single file.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string no File path relative to home. Required (empty returns 400).

Response - 200 OK

{ "versions": [ ... ] }

Returns a bare versions key (the shape of each entry comes from filemanager.GetHistory), not the standard envelope.

Errors

Status Code Meaning
400 bad_request No user resolved, or path missing.
404 not_found website_id did not match a website.

Example

curl "https://panel.example.com:2087/api/filemanager/history?username=user1&path=public_html/index.php" \
  -H "Authorization: Bearer $TOKEN"

GET /api/filemanager/history/all

Returns the version history index for all files that have saved history for the user.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.

Response - 200 OK

{ "files": [ ... ] }

Returns a bare files key (the shape comes from filemanager.GetAllHistory), not the standard envelope.

Errors

Status Code Meaning
400 bad_request No user resolved.
404 not_found website_id did not match a website.

Example

curl "https://panel.example.com:2087/api/filemanager/history/all?username=user1" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/history/clear

Clears saved version history. The path field is passed through to filemanager.ClearHistory.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (optional)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
path string no File path whose history to clear. Passed verbatim to ClearHistory.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 clear_failed Clearing history failed.

Side effects

  • Deletes stored history versions for the file.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/history/clear \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html/index.php"}'

GET /api/filemanager/history/content

Returns the textual content of a specific saved version of a file.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string no File path relative to home. Required (empty returns 400).
version int no Version number; must be an integer in range 1-99.

Response - 200 OK

{ "content": "file contents at this version" }

Returns a bare content key, not the standard envelope.

Errors

Status Code Meaning
400 bad_request No user resolved, path missing, or version missing/out of range (1-99).
404 not_found website_id did not match a website, or the requested version was not found.

Example

curl "https://panel.example.com:2087/api/filemanager/history/content?username=user1&path=public_html/index.php&version=3" \
  -H "Authorization: Bearer $TOKEN"

GET /api/filemanager/history/download

Streams a specific saved version of a file as an attachment download.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string no File path relative to home. Required (empty returns 400).
version int no Version number; must be an integer in range 1-99.

Response - 200 OK

Returns the raw version bytes with a Content-Disposition: attachment header (filename is {basename}-vNN). This endpoint does not use the JSON envelope.

Errors

Status Code Meaning
400 bad_request No user resolved, path missing, or version missing/out of range (1-99).
404 not_found website_id did not match a website, or the requested version was not found.

Example

curl -OJ "https://panel.example.com:2087/api/filemanager/history/download?username=user1&path=public_html/index.php&version=3" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/history/restore

Restores a file to a previously saved version.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (required)",
  "version": "int (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
path string yes File path relative to home.
version int yes Version number to restore. Note: binding:"required", so 0 is rejected.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body (including missing path/version), or no user resolved.
404 not_found website_id did not match a website.
500 restore_failed Restoring the version failed.

Side effects

  • Overwrites the file on disk with the contents of the selected version.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/history/restore \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html/index.php", "version": 3}'

POST /api/filemanager/lock

Sets the immutable attribute (chattr +i) on a file, preventing modification.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. If empty and website_id is set, the username is looked up from the webapps table.
website_id int yes Website id used to resolve the username via SELECT username FROM webapps WHERE id = ?.
path string yes File path relative to the user home.

This handler reads parameters from the query string only (not a JSON body).

Response - 200 OK

{ "data": { "success": true, "locked": true } }

Errors

Status Code Meaning
400 bad_request Neither username nor a resolvable website_id provided.
403 forbidden Resolved path escapes the user home directory.
500 lock_failed The chattr +i command failed (message contains command output).

Side effects

  • Runs chattr +i {path}, setting the immutable flag on the file.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/lock?username=user1&path=public_html/wp-config.php" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/mkdir

Creates a directory within the user home.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
path string yes Directory path relative to home.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 mkdir_failed Directory creation failed.

Side effects

  • Creates a directory on disk.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/mkdir \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html/uploads"}'

POST /api/filemanager/move

Moves a file or directory from a source path to a destination path within the user home.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "src_path": "string (required)",
  "dst_path": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
src_path string yes Source path relative to home.
dst_path string yes Destination path relative to home.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 move_failed Move operation failed.

Side effects

  • Moves the source to the destination path on disk.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/move \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "src_path": "tmp/a.txt", "dst_path": "public_html/a.txt"}'

GET /api/filemanager/read

Reads and returns the textual content of a file.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. If empty, website_id is required.
website_id int yes Website whose owner is the target user. Required when username is absent.
path string yes File path relative to home.

Response - 200 OK

{ "data": { "content": "file contents" } }

Errors

Status Code Meaning
400 bad_request Neither username nor website_id provided.
404 not_found website_id did not match a website.
500 read_failed Reading the file failed.

Example

curl "https://panel.example.com:2087/api/filemanager/read?username=user1&path=public_html/index.php" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/rename

Renames a file or directory within the user home.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "old_path": "string (required)",
  "new_path": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
old_path string yes Existing path relative to home.
new_path string yes New path relative to home.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 rename_failed Rename operation failed.

Side effects

  • Renames the path on disk.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/rename \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "old_path": "old.txt", "new_path": "new.txt"}'

GET /api/filemanager/search

Searches for files under a path matching a query, optionally filtered by type.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. Either this or website_id required.
website_id int yes Website whose owner is the target user.
path string yes Base directory to search, relative to home.
query string yes Search term.
type string yes Filter passed through to filemanager.Search (e.g. file type / scope).

Response - 200 OK

{ "data": { "results": [ ... ] } }

The element shape comes from filemanager.Search.

Errors

Status Code Meaning
400 bad_request No user resolved.
404 not_found website_id did not match a website.
500 search_failed The search operation failed.

Example

curl "https://panel.example.com:2087/api/filemanager/search?username=user1&path=public_html&query=TODO&type=content" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/unlock

Removes the immutable attribute (chattr -i) from a file.

Guards: RequirePermission(db, "websites_management")

Query parameters

Name Type Optional Description
username string yes Target Linux user. If empty and website_id is set, the username is looked up from the webapps table.
website_id int yes Website id used to resolve the username via SELECT username FROM webapps WHERE id = ?.
path string yes File path relative to the user home.

This handler reads parameters from the query string only (not a JSON body).

Response - 200 OK

{ "data": { "success": true, "locked": false } }

Errors

Status Code Meaning
400 bad_request Neither username nor a resolvable website_id provided.
403 forbidden Resolved path escapes the user home directory.
500 unlock_failed The chattr -i command failed (message contains command output).

Side effects

  • Runs chattr -i {path}, clearing the immutable flag on the file.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/unlock?username=user1&path=public_html/wp-config.php" \
  -H "Authorization: Bearer $TOKEN"

POST /api/filemanager/upload

Uploads a single multipart file into a directory within the user home.

Guards: RequirePermission(db, "websites_management")

This endpoint takes multipart/form-data, not JSON.

Form fields

Field Type Required Description
username string no Target Linux user (form field or query param).
website_id int no Website whose owner is the target user (form field or query param).
path string yes Destination directory relative to home.
file file yes The file to upload. The destination filename is basename(uploaded filename).

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request No user resolved, path missing, or file missing.
404 not_found website_id did not match a website.
500 read_failed Reading the uploaded file failed.
500 upload_failed Writing the file to disk failed.

Side effects

  • Writes the uploaded file into {path}/{filename} under the user home.

Example

curl -X POST "https://panel.example.com:2087/api/filemanager/upload?username=user1" \
  -H "Authorization: Bearer $TOKEN" \
  -F "path=public_html" \
  -F "file=@./logo.png"

POST /api/filemanager/wget-upload

Uploads an existing file from the user's home to a transfer.sh-style service via curl and returns the resulting share URL.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (required)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
path string yes Path of the file (relative to home) to upload. Directories are rejected.

Response - 200 OK

{ "url": "https://wget.co.il/abc123/logo.png" }

Returns a bare url key, not the standard envelope. The upload endpoint defaults to https://wget.co.il but can be overridden by the transfersh_url setting (forced to HTTPS).

Errors

Status Code Meaning
400 bad_request Invalid JSON body, no user resolved, unsafe/invalid path, or the path is a directory.
404 not_found website_id did not match a website, or the file does not exist.
500 upload_failed The curl upload failed.

Side effects

  • Runs curl --upload-file {file} {transfershURL}/{filename} to push the file to an external service.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/wget-upload \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html/logo.png"}'

POST /api/filemanager/write

Writes text content to a file, optionally saving the previous version to history first.

Guards: RequirePermission(db, "websites_management")

Request body

{
  "website_id": "int (optional)",
  "username": "string (optional)",
  "path": "string (required)",
  "content": "string (optional)",
  "save_history": "bool (optional)"
}
Field Type Required Description
website_id int no Website whose owner is the target user.
username string no Target Linux user.
path string yes File path relative to home.
content string no New file content.
save_history bool no If true, snapshots the existing file into version history before overwriting.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Invalid JSON body, or no user resolved.
404 not_found website_id did not match a website.
500 write_failed Writing the file failed.

Side effects

  • When save_history is set, stores a history snapshot of the current file.
  • Overwrites the file on disk with the provided content.

Example

curl -X POST https://panel.example.com:2087/api/filemanager/write \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "path": "public_html/index.php", "content": "<?php echo 1; ?>", "save_history": true}'