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:
On error:
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
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
recursiveis 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
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
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
| 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
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
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
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
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:
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
gitcommands (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
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | yes | Repository URL to clone. |
Response - 200 OK
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
| 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
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, thengit 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
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 diffin 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
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(orgit init), creating a.gitdirectory.
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 login 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
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
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 pushto 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
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | yes | Remote URL. |
name |
string | no | Remote name; defaults to origin. |
Response - 200 OK
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(orgit 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
| Field | Type | Required | Description |
|---|---|---|---|
hash |
string | yes | Commit hash to revert. |
Response - 200 OK
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}thengit 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 showcommands 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
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
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
| 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
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
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
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
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
| 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
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
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
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
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
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
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
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
| 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
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
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_historyis set, stores a history snapshot of the current file. - Overwrites the file on disk with the provided content.
Example