API HiTechCloud
HiTechCloud cung cấp một REST API đầy đủ, phản chiếu mọi chức năng của giao diện web. Mọi tính năng có trong panel đều có thể truy cập bằng chương trình.
Cũng có sẵn một đặc tả OpenAPI 3.0 đọc được bằng máy, bao quát mọi endpoint bên dưới — hãy nhập vào Postman/Insomnia, sinh SDK máy khách, hoặc nạp vào Swagger UI/Redoc.
Xác thực
Mọi yêu cầu, trừ endpoint đăng nhập, đều mang một Bearer token.
API là một tính năng Enterprise. Cả cờ tính năng chung api và
cờ tính năng riêng của endpoint bạn gọi đều phải được gói hosting
của tài khoản cấp.
POST /api/login
Tuyến duy nhất nhận mật khẩu. Gửi JSON:
| Trường | Bắt buộc | Ý nghĩa |
|---|---|---|
username | có | Tên người dùng panel. |
password | có | Mật khẩu của người dùng đó. |
twofa_code | chỉ khi tài khoản bật 2FA | Một mã TOTP hiện hành. |
curl -s -X POST https://panel.example.com/api/login \
-H "Content-Type: application/json" \
-d '{"username": "stefan", "password": "yourpassword"}'
Khi thành công — 200:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user_id": 1,
"expires_in": 3600
}
Token là một JWT HS256 có chủ thể là id người dùng dạng số, có hiệu lực
một giờ (expires_in tính bằng giây). Không có refresh token; hãy đăng nhập
lại.
Đăng nhập thành công là một lần đăng nhập thật: nó được ghi vào lịch sử đăng nhập
và nhật ký hoạt động của tài khoản dưới dạng logged in via user API, và kích hoạt
thông báo đăng nhập của tài khoản nếu tuỳ chọn đó đang bật.
Nếu tài khoản có xác thực hai yếu tố và không gửi twofa_code —
401:
{"twofa_required": true, "user_id": 1}
Hãy thử lại với twofa_code trong phần thân. Mã không hợp lệ trả về 401
kèm {"error": "invalid_2fa"}.
Thất bại. Thiếu username hoặc password trả về 400. Mọi trường hợp khác trả v ề
401 kèm một mã error ổn định, đọc được bằng máy:
| Mã | Ý nghĩa |
|---|---|
invalid_password | Mật khẩu sai. |
unknown_user | Không có tài khoản như vậy. |
suspended | Tài khoản đang bị tạm ngưng. |
db_error | Panel không kết nối được tới cơ sở dữ liệu của nó. |
login_failed | Bất kỳ lỗi nào khác. |
token_generation_failed và internal_error trả về 500.
Giới hạn tần suất. Các lần đăng nhập được đếm theo IP máy khách trong một cửa sổ
cố định một phút. Giới hạn là cài đặt login_ratelimit của panel, mặc định 5 lần mỗi
phút. Vượt quá, yêu cầu không bao giờ tới bước kiểm tra mật khẩu và
câu trả lời là 429:
{"error":"rate_limit_exceeded","message":"Too many requests. Please try again later."}
Mỗi lần bị chặn tần suất được ghi vào /var/log/hitechcloud/user/failed_login.log
và tính vào IP đó. Khi bộ đếm vượt login_blocklimit (mặc định 20),
IP bị cấm tạm thời một giờ trong ConfigServer Firewall, nếu đã cài
CSF. Đăng nhập thành công sẽ xoá bộ đếm của IP. Các bộ đếm nằm
trong tiến trình panel, nên khởi động lại panel sẽ xoá chúng.
POST /api/auth/ticket và POST /api/auth/ticket/redeem
Vé đăng nhập dùng một lần cho phép một ứng dụng đã đăng nhập mở một ứng dụng HiTechCloud khác
mà đã ở trạng thái đăng nhập. Lệnh gọi đầu nhận Bearer token của bạn và trả về một vé
sống 30 giây (tối đa 60) và chỉ dùng được một lần; lệnh gọi thứ hai nhận vé
mà không cần token, và trả lời giống POST /api/login. Toàn bộ hợp đồng nằm ở
Vé đăng nhập ứng dụng.
Dùng token
curl https://panel.example.com/api/account \
-H "Authorization: Bearer eyJhbGciOi..."
MySQL
Mọi endpoint MySQL đều phẳng — không có kiểu lồng /api/mysql/<db_name>/users. Cơ sở dữ liệu nằm dưới /api/mysql/databases, người dùng dưới /api/mysql/users, và hai thứ được gắn với nhau bằng một tài nguyên riêng /api/mysql/grants.
Liệt kê cơ sở dữ liệu
GET /api/mysql/databases
Authorization: Bearer <token>
{
"databases": [
{"name": "mydb", "assigned_users": "myuser"}
],
"total": 1
}
Tạo cơ sở dữ liệu
POST /api/mysql/databases
Content-Type: application/json
{"name": "newdb"}
Xoá cơ sở dữ liệu
DELETE /api/mysql/databases/newdb
Liệt kê các bảng trong một cơ sở dữ liệu
GET /api/mysql/databases/mydb/tables
{
"database": "mydb",
"tables": [
{"table": "wp_posts", "rows": 120, "data_length": 98304, "index_length": 32768, "data_free": 0}
]
}
Tối ưu / sửa chữa một cơ sở dữ liệu
Chạy OPTIMIZE TABLE hoặc REPAIR TABLE trên mọi bảng trong cơ sở dữ liệu.
POST /api/mysql/databases/mydb/optimize
POST /api/mysql/databases/mydb/repair
{
"database": "mydb",
"action": "optimize",
"results": [
{"table": "wp_posts", "status": "ok", "details": [{"op": "optimize", "msg_type": "status", "msg_text": "OK"}]}
]
}
Xuất một cơ sở dữ liệu
Truyền trực tiếp (stream) một tệp .sql hoặc .sql.gz để tải xuống.
GET /api/mysql/databases/mydb/export?format=sql
Nhập một cơ sở dữ liệu
Tải lên dạng multipart — tên trường phải là file. Chấp nhận .sql hoặc .sql.gz.
POST /api/mysql/databases/mydb/import
Content-Type: multipart/form-data
file=@dump.sql
Lấy dung lượng đĩa của từng cơ sở dữ liệu
Phản chiếu chế độ xem kích thước cơ sở dữ liệu của giao diện web — khác với /api/mysql/info, không có dữ liệu kích thước, và /api/mysql/databases/<db>/tables, tính theo từng bảng của một cơ sở dữ liệu.
GET /api/mysql/size?unit=mb&show_all=false
{"sizes": [{"database": "mydb", "size": 12.4}], "total": 1, "unit": "MB"}
Đặt mật khẩu root của MySQL
Chỉ ghi — không thể lấy lại mật khẩu hiện tại. Cập nhật cả hai host % và localhost và khởi động lại dịch vụ.
PUT /api/mysql/root-password
Content-Type: application/json
{"password": "newRootPass123"}
Liệt kê người dùng cơ sở dữ liệu
GET /api/mysql/users
{"users": ["myuser", "shopuser"], "total": 2}
Tạo người dùng cơ sở dữ liệu
POST /api/mysql/users
Content-Type: application/json
{"username": "dbuser", "password": "securepass", "host": "%"}
host mặc định là % nếu bỏ qua.
Xoá người dùng cơ sở dữ liệu
DELETE /api/mysql/users/dbuser?host=%
Đổi mật khẩu của người dùng cơ sở dữ liệu
PATCH /api/mysql/users/dbuser/password
Content-Type: application/json
{"password": "newpass", "host": "%"}
Lấy quyền của một người dùng trên một cơ sở dữ liệu
GET /api/mysql/users/dbuser/privileges/mydb?host=%
{"username": "dbuser", "host": "%", "database": "mydb", "privileges": ["ALL PRIVILEGES"]}
Cấp quyền
POST /api/mysql/grants
Content-Type: application/json
{"username": "dbuser", "database": "mydb", "privileges": ["ALL PRIVILEGES"], "host": "%"}
Thu hồi quyền
DELETE /api/mysql/grants
Content-Type: application/json
{"username": "dbuser", "database": "mydb", "host": "%"}
Lấy bản tóm tắt cơ sở dữ liệu/người dùng/phân quyền
GET /api/mysql/info
{
"databases": ["mydb", "shop"],
"users": ["dbuser", "shopuser"],
"assigned_databases": [{"database": "mydb", "users": "dbuser"}]
}
Hiện danh sách tiến trình đầy đủ
GET /api/mysql/processlist
{
"processlist": [
{"id": 42, "user": "dbuser", "host": "localhost", "db": "mydb", "command": "Query", "time": 0, "state": "", "info": "SELECT 1"}
],
"total": 1
}
Trạng thái truy cập từ xa
GET /api/mysql/remote-access
{
"enabled": false,
"server_ip": "203.0.113.10",
"port": "3306",
"user_access": [{"username": "dbuser", "hosts": ["%"]}]
}
Bật / tắt truy cập từ xa
POST /api/mysql/remote-access
Content-Type: application/json
{"action": "enable"}
Cấp một mục truy cập từ xa
Tạo một user@host mới (sao chép các quyền từ một host sẵn có của người dùng đó, nếu có).
POST /api/mysql/remote-access/entries
Content-Type: application/json
{"username": "dbuser", "host": "1.2.3.4", "password": "securepass"}
Đổi host của một mục truy cập từ xa
PATCH /api/mysql/remote-access/entries
Content-Type: application/json
{"username": "dbuser", "old_host": "1.2.3.4", "new_host": "5.6.7.8"}
Gỡ một mục truy cập từ xa
DELETE /api/mysql/remote-access/entries
Content-Type: application/json
{"username": "dbuser", "host": "1.2.3.4"}
Lấy cấu hình máy chủ
GET /api/mysql/configuration
{
"configuration": {"max_connections": "150"},
"available_keys": ["max_connections", "max_allowed_packet", "innodb_buffer_pool_size", "..."]
}
Cập nhật cấu hình máy chủ
Chỉ các khoá có trong available_keys được chấp nhận. Khởi động lại MySQL/MariaDB.
PUT /api/mysql/configuration
Content-Type: application/json
{"max_connections": "200"}
{"updated": true, "restarted": true, "configuration": {"max_connections": "200"}}
PostgreSQL
Cấu trúc phẳng giống MySQL: cơ sở dữ liệu, người dùng và phân quyền là các tài nguyên cấp cao nhất riêng biệt.
Liệt kê cơ sở dữ liệu
GET /api/postgresql/databases
{
"databases": [{"name": "pgdb", "assigned_users": "pguser"}],
"total": 1
}
Tạo cơ sở dữ liệu
POST /api/postgresql/databases
Content-Type: application/json
{"name": "pgdb"}
Xoá cơ sở dữ liệu
DELETE /api/postgresql/databases/pgdb
Xuất một cơ sở dữ liệu
Truyền trực tiếp một bản dump .sql.
GET /api/postgresql/databases/pgdb/export
Nhập một cơ sở dữ liệu
Tải lên dạng multipart — tên trường phải là file.
POST /api/postgresql/databases/pgdb/import
Content-Type: multipart/form-data
file=@dump.sql
{"database": "pgdb", "file": "dump.sql", "imported": true}
Liệt kê người dùng
GET /api/postgresql/users
{"users": ["pguser"], "total": 1}
Tạo người dùng
POST /api/postgresql/users
Content-Type: application/json
{"username": "pguser", "password": "securepass"}
Xoá người dùng
Thu hồi quyền truy cập khỏi mọi cơ sở dữ liệu trước khi xoá vai trò.
DELETE /api/postgresql/users/pguser
Đổi mật khẩu của người dùng
PATCH /api/postgresql/users/pguser/password
Content-Type: application/json
{"password": "newpass"}
Cấp mọi quyền trên một cơ sở dữ liệu
POST /api/postgresql/grants
Content-Type: application/json
{"username": "pguser", "database": "pgdb"}
Thu hồi quyền
DELETE /api/postgresql/grants
Content-Type: application/json
{"username": "pguser", "database": "pgdb"}
Lấy bản tóm tắt cơ sở dữ liệu/người dùng/phân quyền
GET /api/postgresql/info
Hiện các kết nối đang hoạt động
GET /api/postgresql/processlist
{
"processlist": [
{"pid": 123, "user": "pguser", "application": "psql", "client_addr": "127.0.0.1",
"state": "active", "wait_event_type": "", "wait_event": "", "query": "SELECT 1",
"backend_type": "client backend", "duration": "0:00:00.001"}
],
"total": 1
}
Trạng thái truy cập từ xa
GET /api/postgresql/remote-access
{"enabled": false, "server_ip": "203.0.113.10", "port": "5432", "postgres_port": 5432}
Bật / tắt truy cập từ xa
POST /api/postgresql/remote-access
Content-Type: application/json
{"action": "enable"}
Lấy / cập nhật cấu hình máy chủ
Cùng dạng với cấu hình MySQL — khởi động lại PostgreSQL khi lưu.
GET /api/postgresql/configuration
PUT /api/postgresql/configuration
Content-Type: application/json
{"max_connections": "200"}