This document provides complete REST API documentation for ServerKit.
Base URL: http://localhost:5000/api/v1
Content Type: All requests and responses use application/json
Authentication: JWT Bearer tokens (except where noted)
Authenticate and receive access tokens.
POST /auth/loginRate Limit: 5 requests per minute
Request Body:
{
"email": "user@example.com",
"password": "your-password"
}Response (200):
{
"user": {
"id": 1,
"email": "user@example.com",
"username": "admin",
"role": "admin"
},
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}Response (2FA Required):
{
"requires_2fa": true,
"temp_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"message": "Two-factor authentication required"
}Create a new user account. The first registered user becomes admin.
POST /auth/registerRate Limit: 3 requests per minute
Request Body:
{
"email": "user@example.com",
"username": "newuser",
"password": "secure-password"
}Response (201):
{
"message": "User registered successfully",
"user": {
"id": 1,
"email": "user@example.com",
"username": "newuser",
"role": "admin"
},
"access_token": "...",
"refresh_token": "..."
}Get a new access token using a refresh token.
POST /auth/refresh
Authorization: Bearer <refresh_token>Response (200):
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}GET /auth/me
Authorization: Bearer <access_token>Response (200):
{
"user": {
"id": 1,
"email": "user@example.com",
"username": "admin",
"role": "admin",
"totp_enabled": true
}
}PUT /auth/me
Authorization: Bearer <access_token>Request Body:
{
"username": "newusername",
"email": "newemail@example.com",
"password": "new-password"
}Generate a TOTP secret and QR code for setup.
POST /2fa/setup
Authorization: Bearer <access_token>Response (200):
{
"secret": "BASE32SECRET",
"qr_code": "data:image/png;base64,...",
"backup_codes": ["12345678", "87654321", ...]
}Verify and enable 2FA after setup.
POST /2fa/enable
Authorization: Bearer <access_token>Request Body:
{
"code": "123456"
}Complete login with 2FA code.
POST /2fa/verify
Authorization: Bearer <temp_token>Request Body:
{
"code": "123456"
}Response (200):
{
"user": {...},
"access_token": "...",
"refresh_token": "..."
}POST /2fa/disable
Authorization: Bearer <access_token>Request Body:
{
"code": "123456"
}All system endpoints require admin role.
GET /system/metrics
Authorization: Bearer <access_token>Response (200):
{
"cpu": {
"percent": 15.2,
"count": 4,
"freq_current": 2400.0
},
"memory": {
"total": 8589934592,
"available": 4294967296,
"percent": 50.0,
"used": 4294967296
},
"disk": {
"total": 107374182400,
"used": 53687091200,
"free": 53687091200,
"percent": 50.0
},
"network": {
"bytes_sent": 1234567890,
"bytes_recv": 9876543210
}
}GET /system/cpuGET /system/memoryGET /system/diskGET /system/networkGET /system/processesResponse (200):
{
"processes": [
{
"pid": 1234,
"name": "python",
"cpu_percent": 5.2,
"memory_percent": 2.1,
"status": "running"
}
]
}GET /system/servicesResponse (200):
{
"services": [
{"name": "nginx", "status": "running"},
{"name": "mysql", "status": "running"},
{"name": "docker", "status": "stopped"}
]
}No authentication required.
GET /system/healthResponse (200):
{
"status": "healthy",
"service": "serverkit-api"
}GET /apps
Authorization: Bearer <access_token>Response (200):
{
"apps": [
{
"id": 1,
"name": "my-app",
"app_type": "php",
"status": "running",
"php_version": "8.2",
"port": 8080,
"root_path": "/var/www/my-app",
"created_at": "2024-01-01T00:00:00Z"
}
]
}GET /apps/:id
Authorization: Bearer <access_token>POST /apps
Authorization: Bearer <access_token>Request Body:
{
"name": "my-app",
"app_type": "php",
"php_version": "8.2",
"port": 8080,
"root_path": "/var/www/my-app"
}Valid app_type values: php, wordpress, flask, django, docker, static
PUT /apps/:id
Authorization: Bearer <access_token>DELETE /apps/:id
Authorization: Bearer <access_token>POST /apps/:id/start
Authorization: Bearer <access_token>POST /apps/:id/stop
Authorization: Bearer <access_token>POST /apps/:id/restart
Authorization: Bearer <access_token>GET /apps/:app_id/env
Authorization: Bearer <access_token>Response (200):
{
"env_vars": [
{
"id": 1,
"key": "DATABASE_URL",
"is_secret": true,
"created_at": "2024-01-01T00:00:00Z"
}
]
}POST /apps/:app_id/env
Authorization: Bearer <access_token>Request Body:
{
"key": "DATABASE_URL",
"value": "postgresql://user:pass@localhost/db",
"is_secret": true
}DELETE /apps/:app_id/env/:key
Authorization: Bearer <access_token>GET /domains
Authorization: Bearer <access_token>POST /domains
Authorization: Bearer <access_token>Request Body:
{
"domain": "example.com",
"app_id": 1
}DELETE /domains/:id
Authorization: Bearer <access_token>GET /ssl/certificates
Authorization: Bearer <access_token>Request a Let's Encrypt certificate.
POST /ssl/issue
Authorization: Bearer <access_token>Request Body:
{
"domain": "example.com",
"email": "admin@example.com"
}POST /ssl/renew/:domain
Authorization: Bearer <access_token>GET /databases
Authorization: Bearer <access_token>POST /databases
Authorization: Bearer <access_token>Request Body:
{
"name": "my_database",
"type": "mysql",
"charset": "utf8mb4"
}DELETE /databases/:id
Authorization: Bearer <access_token>POST /databases/:id/users
Authorization: Bearer <access_token>GET /docker/containers
Authorization: Bearer <access_token>GET /docker/containers/:id
Authorization: Bearer <access_token>POST /docker/containers/:id/start
Authorization: Bearer <access_token>POST /docker/containers/:id/stop
Authorization: Bearer <access_token>GET /docker/containers/:id/logs
Authorization: Bearer <access_token>GET /docker/images
Authorization: Bearer <access_token>GET /files?path=/var/www
Authorization: Bearer <access_token>Response (200):
{
"files": [
{
"name": "index.html",
"path": "/var/www/index.html",
"type": "file",
"size": 1234,
"modified": "2024-01-01T00:00:00Z"
}
]
}GET /files/read?path=/var/www/index.html
Authorization: Bearer <access_token>POST /files/write
Authorization: Bearer <access_token>Request Body:
{
"path": "/var/www/index.html",
"content": "<html>...</html>"
}DELETE /files?path=/var/www/old-file.txt
Authorization: Bearer <access_token>GET /cron
Authorization: Bearer <access_token>POST /cron
Authorization: Bearer <access_token>Request Body:
{
"name": "Daily Backup",
"command": "/usr/local/bin/backup.sh",
"schedule": "0 2 * * *",
"enabled": true
}PUT /cron/:id
Authorization: Bearer <access_token>DELETE /cron/:id
Authorization: Bearer <access_token>GET /firewall/status
Authorization: Bearer <access_token>GET /firewall/rules
Authorization: Bearer <access_token>POST /firewall/rules
Authorization: Bearer <access_token>Request Body:
{
"port": 443,
"protocol": "tcp",
"action": "allow",
"direction": "in"
}DELETE /firewall/rules/:id
Authorization: Bearer <access_token>POST /firewall/enable
POST /firewall/disable
Authorization: Bearer <access_token>GET /security/status
Authorization: Bearer <access_token>Response (200):
{
"clamav_installed": true,
"clamav_running": true,
"last_scan": "2024-01-01T00:00:00Z",
"threats_found": 0,
"quarantined_files": 3,
"integrity_initialized": true
}GET /security/clamav/status
Authorization: Bearer <access_token>POST /security/clamav/install
Authorization: Bearer <access_token>POST /security/clamav/update
Authorization: Bearer <access_token>POST /security/scan/file
Authorization: Bearer <access_token>Request Body:
{
"path": "/var/www/suspicious-file.php"
}POST /security/scan/directory
Authorization: Bearer <access_token>Request Body:
{
"path": "/var/www/html",
"recursive": true
}Scan common web directories.
POST /security/scan/quick
Authorization: Bearer <access_token>Scan entire system.
POST /security/scan/full
Authorization: Bearer <access_token>GET /security/quarantine
Authorization: Bearer <access_token>POST /security/quarantine
Authorization: Bearer <access_token>Request Body:
{
"path": "/var/www/malware.php"
}DELETE /security/quarantine/:id
Authorization: Bearer <access_token>POST /security/integrity/initialize
Authorization: Bearer <access_token>Request Body:
{
"paths": ["/var/www", "/etc/nginx"]
}GET /security/integrity/check
Authorization: Bearer <access_token>GET /security/failed-logins
Authorization: Bearer <access_token>GET /security/events
Authorization: Bearer <access_token>GET /notifications/status
Authorization: Bearer <access_token>GET /notifications/config
Authorization: Bearer <access_token>PUT /notifications/config/:channel
Authorization: Bearer <access_token>Channels: discord, slack, telegram, webhook
Request Body (Discord):
{
"enabled": true,
"webhook_url": "https://discord.com/api/webhooks/...",
"severity_levels": ["warning", "critical"]
}POST /notifications/test/:channel
Authorization: Bearer <access_token>POST /notifications/test
Authorization: Bearer <access_token>GET /monitoring/status
Authorization: Bearer <access_token>GET /monitoring/thresholds
Authorization: Bearer <access_token>PUT /monitoring/thresholds
Authorization: Bearer <access_token>Request Body:
{
"cpu_warning": 70,
"cpu_critical": 90,
"memory_warning": 80,
"memory_critical": 95,
"disk_warning": 80,
"disk_critical": 95
}GET /monitoring/alerts
Authorization: Bearer <access_token>GET /uptime/history
Authorization: Bearer <access_token>GET /uptime/stats
Authorization: Bearer <access_token>All endpoints return consistent error responses:
{
"error": "Error message describing what went wrong"
}| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request - Invalid input |
| 401 | Unauthorized - Invalid or missing token |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource doesn't exist |
| 409 | Conflict - Resource already exists |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error |
Some endpoints have rate limits:
| Endpoint | Limit |
|---|---|
| POST /auth/login | 5/minute |
| POST /auth/register | 3/minute |
When rate limited, you'll receive a 429 response with retry information.
ServerKit uses Socket.IO for real-time updates.
Connection:
const socket = io('http://localhost:5000', {
auth: { token: 'your-access-token' }
});Events:
| Event | Description |
|---|---|
metrics |
Real-time system metrics |
alert |
New alert triggered |
scan_progress |
Malware scan progress |
scan_complete |
Scan finished |
# Login
TOKEN=$(curl -s -X POST http://localhost:5000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"password"}' \
| jq -r '.access_token')
# Get system metrics
curl -s http://localhost:5000/api/v1/system/metrics \
-H "Authorization: Bearer $TOKEN" | jq
# Create application
curl -s -X POST http://localhost:5000/api/v1/apps \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"my-app","app_type":"php","php_version":"8.2"}'import requests
BASE_URL = "http://localhost:5000/api/v1"
# Login
response = requests.post(f"{BASE_URL}/auth/login", json={
"email": "admin@example.com",
"password": "password"
})
token = response.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
# Get metrics
metrics = requests.get(f"{BASE_URL}/system/metrics", headers=headers).json()
print(f"CPU: {metrics['cpu']['percent']}%")const BASE_URL = 'http://localhost:5000/api/v1';
// Login
const loginRes = await fetch(`${BASE_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'admin@example.com',
password: 'password'
})
});
const { access_token } = await loginRes.json();
// Get metrics
const metricsRes = await fetch(`${BASE_URL}/system/metrics`, {
headers: { 'Authorization': `Bearer ${access_token}` }
});
const metrics = await metricsRes.json();
console.log(`CPU: ${metrics.cpu.percent}%`);
ServerKit API Reference
Version 0.9.0