Skip to main content

Public Routes

Health Check

Request: GET /api/v1/public/ping Response (200):
{
  "status": "ok",
  "message": "Lightd is running"
}

Authentication

Generate Token

Request: POST /auth/tokens
{
  "ttl": "1h",
  "remove_on_use": false
}
Response (200):
{
  "token": "lightd_f3a8b9c2d1e4f5a6b7c8d9e0f1a2b3c4",
  "expires_at": "2026-01-28T15:30:00Z"
}

Volume Management

Create Volume

Request: POST /volumes Response (201):
{
  "volume_id": "d6764075-c5f1-4045-9fb3-85315b85cb0f",
  "path": "/storage/volumes/d6764075-c5f1-4045-9fb3-85315b85cb0f"
}

Write File

Request: POST /volumes/d6764075/files
{
  "path": "config/server.properties",
  "content": "server-port=25565\nmax-players=20"
}
Response (200):
{
  "message": "File written successfully",
  "path": "config/server.properties"
}

Create Folder

Request: POST /volumes/d6764075/folders
{
  "path": "plugins/MyPlugin"
}
Response (200):
{
  "message": "Folder created successfully",
  "path": "plugins/MyPlugin"
}

Copy File/Folder

Request: POST /volumes/d6764075/copy
{
  "source": "plugins",
  "destination": "backup/plugins"
}
Response (200):
{
  "message": "Copied successfully",
  "source": "plugins",
  "destination": "backup/plugins"
}

List Files

Request: GET /volumes/d6764075/files?path=plugins Response (200):
{
  "files": [
    {
      "name": "MyPlugin",
      "type": "directory",
      "size": 0
    },
    {
      "name": "config.yml",
      "type": "file",
      "size": 1024
    }
  ]
}

Compress Volume

Request: POST /volumes/d6764075/compress
{
  "format": "tar.gz",
  "output_name": "backup"
}
Response (200):
{
  "message": "Compression successful",
  "archive_path": "backup.tar.gz",
  "size": 2048576
}

Decompress Archive

Request: POST /volumes/d6764075/decompress
{
  "archive_path": "backup.tar.gz",
  "destination": "restored"
}
Response (200):
{
  "message": "Decompression successful",
  "destination": "restored"
}

Network Management

Add Port

Request: POST /network/ports
{
  "ip": "0.0.0.0",
  "port": 25565,
  "protocol": "tcp"
}
Response (200):
{
  "message": "Port added to pool",
  "ip": "0.0.0.0",
  "port": 25565,
  "protocol": "tcp"
}

Get Port

Request: GET /network/ports/0.0.0.0/25565 Response (200):
{
  "ip": "0.0.0.0",
  "port": 25565,
  "protocol": "tcp",
  "in_use": false
}

List All Ports

Request: GET /network/ports Response (200):
{
  "ports": [
    {
      "ip": "0.0.0.0",
      "port": 25565,
      "protocol": "tcp",
      "in_use": false
    },
    {
      "ip": "0.0.0.0",
      "port": 25566,
      "protocol": "tcp",
      "in_use": true
    },
    {
      "ip": "0.0.0.0",
      "port": 19132,
      "protocol": "udp",
      "in_use": false
    }
  ]
}

Get Random Available Port

Request: GET /network/ports/random Response (200):
{
  "ip": "0.0.0.0",
  "port": 25567,
  "protocol": "tcp",
  "in_use": false
}

Mark Port In Use

Request: PUT /network/ports/0.0.0.0/25565/use
{
  "in_use": true
}
Response (200):
{
  "message": "Port usage updated",
  "ip": "0.0.0.0",
  "port": 25565,
  "in_use": true
}

Delete Port

Request: DELETE /network/ports/0.0.0.0/25565 Response (200):
{
  "message": "Port deleted from pool"
}

Bulk Delete Ports

Request: POST /network/ports/bulk-delete
{
  "ports": [
    {"ip": "0.0.0.0", "port": 25565},
    {"ip": "0.0.0.0", "port": 25566}
  ]
}
Response (200):
{
  "message": "Deleted 2 ports from pool",
  "deleted_count": 2
}

Container Management

Create Container

Request: POST /containers
{
  "internal_id": "minecraft-001",
  "image": "openjdk:17-slim",
  "volume_id": "d6764075-c5f1-4045-9fb3-85315b85cb0f",
  "startup_command": "java -Xmx1G -jar server.jar nogui",
  "start_pattern": "Done.*For help",
  "ports": [
    {
      "ip": "0.0.0.0",
      "port": 25565,
      "protocol": "tcp"
    }
  ],
  "limits": {
    "memory": 1073741824,
    "cpu": 2.0
  },
  "install_script": "#!/bin/bash\nwget https://example.com/server.jar"
}
Response (200):
{
  "message": "Container creation started",
  "internal_id": "minecraft-001",
  "state": "installing"
}

Get Container State

Request: GET /containers/minecraft-001 Response (200):
{
  "internal_id": "minecraft-001",
  "container_id": "a1b2c3d4e5f6789",
  "volume_id": "d6764075-c5f1-4045-9fb3-85315b85cb0f",
  "image": "openjdk:17-slim",
  "startup_command": "java -Xmx1G -jar server.jar nogui",
  "start_pattern": "Done.*For help",
  "install_state": "ready",
  "ports": [
    {
      "ip": "0.0.0.0",
      "port": 25565,
      "protocol": "tcp"
    }
  ],
  "limits": {
    "memory": 1073741824,
    "cpu": 2.0
  },
  "mount": {},
  "created_at": 1706450000,
  "updated_at": 1706450100
}

List All Containers

Request: GET /containers Response (200):
{
  "containers": [
    {
      "internal_id": "minecraft-001",
      "container_id": "a1b2c3d4e5f6789",
      "install_state": "ready",
      "image": "openjdk:17-slim"
    },
    {
      "internal_id": "web-server-001",
      "container_id": "b2c3d4e5f6a7890",
      "install_state": "ready",
      "image": "nginx:latest"
    }
  ]
}

Delete Container

Request: DELETE /containers/minecraft-001 Response (200):
{
  "message": "Container deleted successfully"
}

Start Container

Request: POST /containers/minecraft-001/start Response (200):
{
  "message": "Container start initiated",
  "internal_id": "minecraft-001"
}

Kill Container

Request: POST /containers/minecraft-001/kill Response (200):
{
  "message": "Container kill initiated",
  "internal_id": "minecraft-001"
}

Restart Container

Request: POST /containers/minecraft-001/restart Response (200):
{
  "message": "Container restart initiated",
  "internal_id": "minecraft-001"
}

Reinstall Container

Request: POST /containers/minecraft-001/reinstall
{
  "image": "openjdk:17-slim",
  "install_script": "#!/bin/bash\nwget https://example.com/server.jar"
}
Response (200):
{
  "message": "Container reinstall started",
  "internal_id": "minecraft-001"
}

Rebind Network

Request: POST /containers/minecraft-001/rebind-network
{
  "ports": [
    {
      "ip": "0.0.0.0",
      "port": 25566,
      "protocol": "tcp"
    }
  ]
}
Response (200):
{
  "message": "Network rebinding started",
  "internal_id": "minecraft-001"
}

Remote API

Get Config

Request: GET /remote/config Response (200):
{
  "version": "0.1.0",
  "server": {
    "host": "0.0.0.0",
    "port": 8070
  },
  "authorization": {
    "enabled": true,
    "token": "lightd_ad2f7fc49ed640429c450e14ed07c8d5"
  },
  "remote": {
    "enabled": true,
    "url": "https://remote-api.com/api",
    "token": "lightd_ad2f7fc49ed640429c450e14ed07c8d5"
  }
}

Reload Config

Request: POST /remote/config/reload Response (200):
{
  "message": "Configuration reloaded successfully"
}

WebSocket Events

Stats Event

{
  "event": "stats",
  "cpu_usage": 25.5,
  "memory_usage": 536870912,
  "memory_limit": 1073741824,
  "network_rx": 1024000,
  "network_tx": 2048000,
  "block_read": 4096000,
  "block_write": 8192000
}

Console Output

{
  "event": "console",
  "data": "[Server] Starting Minecraft server version 1.20.4\n"
}

State Events

{
  "event": "event",
  "data": "installing"
}
{
  "event": "event",
  "data": "ready"
}
{
  "event": "event",
  "data": "starting"
}
{
  "event": "event",
  "data": "running"
}
{
  "event": "event",
  "data": "exit"
}

Daemon Messages

{
  "event": "daemon_message",
  "data": "Container started"
}

Historical Logs

{
  "event": "logs",
  "data": "[10:30:15] Starting server...\n[10:30:16] Loading world...\n[10:30:20] Done!\n"
}

Error Responses

Unauthorized (401)

{
  "error": "Missing or invalid authorization token"
}

Forbidden (403)

{
  "error": "Invalid vendor header"
}

Not Found (404)

{
  "error": "Container not found"
}
{
  "error": "Volume not found"
}
{
  "error": "Port not found in pool"
}

Bad Request (400)

{
  "error": "Invalid path: path traversal detected"
}
{
  "error": "Cannot rebind network while container is installing"
}
{
  "error": "Port already exists in pool"
}
{
  "error": "Invalid port binding: port not in network pool"
}

Internal Server Error (500)

{
  "error": "Failed to create Docker container: image not found"
}
{
  "error": "Database operation failed"
}
{
  "error": "Failed to write file: permission denied"
}