The Terminal System Monitoring API exposes system-level operations on a Hoody node. Use these endpoints to inspect running processes, audit network listeners, query resource utilization, manage connected displays, and control system power. All endpoints require an authenticated Hoody session except /api/v1/terminal/health, which is unauthenticated and always returns 200 when the service is running.
Service Health
Section titled “Service Health”GET /api/v1/terminal/health
Section titled “GET /api/v1/terminal/health”Returns the standardized 9-field health response. Always returns HTTP 200 with application/json when the terminal service is up. Unauthenticated.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/terminal/healthconst health = await client.terminal.health.check();{ "status": "healthy", "service": "terminal", "version": "1.4.2", "uptime_seconds": 86400, "timestamp": "2025-01-15T10:30:00Z", "database": { "status": "ok", "latency_ms": 2 }, "daemon": { "status": "ok" }, "memory": { "used": 134217728, "total": 268435456 }, "goroutines": 42}System Resources
Section titled “System Resources”GET /api/v1/system/resources
Section titled “GET /api/v1/system/resources”Returns comprehensive system statistics including CPU usage, memory, network interfaces, uptime, and disk usage.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/system/resources \ -H "Authorization: Bearer <token>"const stats = await client.terminal.system.getResources();{ "cpu": { "usage_percent": 12.5, "cores": 8, "load_average": [0.5, 0.7, 0.9] }, "memory": { "total": 16777216000, "used": 8589934592, "free": 8187281408, "usage_percent": 51.2 }, "disk": { "total": 500107862016, "used": 250053931008, "free": 250053931008, "usage_percent": 50.0 }, "network": [ { "name": "eth0", "bytes_sent": 1234567890, "bytes_received": 9876543210, "packets_sent": 8765432, "packets_received": 12345678 } ], "uptime_seconds": 86400}Daemon Programs
Section titled “Daemon Programs”GET /api/v1/system/daemon
Section titled “GET /api/v1/system/daemon”Returns the JSON array of daemon programs from the hoody-daemon configuration.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/system/daemon \ -H "Authorization: Bearer <token>"const daemons = await client.terminal.system.getDaemonConfig();[ { "name": "hoody-daemon", "command": "/usr/local/bin/hoody-daemon", "autostart": true, "restart": "on-failure" }, { "name": "kit-watchdog", "command": "/usr/local/bin/kit-watchdog", "autostart": true, "restart": "always" }]Displays
Section titled “Displays”GET /api/v1/system/displays
Section titled “GET /api/v1/system/displays”Returns information about connected displays from the external display script.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/system/displays \ -H "Authorization: Bearer <token>"const displays = await client.terminal.system.getDisplayInfo();[ { "name": "DisplayPort-0", "resolution": "3840x2160", "position": [0, 0], "primary": true, "scale": 1.0, "refresh_rate": 60 }, { "name": "HDMI-A-1", "resolution": "1920x1080", "position": [3840, 0], "primary": false, "scale": 1.0, "refresh_rate": 60 }]Processes
Section titled “Processes”GET /api/v1/system/processes
Section titled “GET /api/v1/system/processes”Returns a JSON array of all processes with CPU, memory, and state information. Supports filtering, sorting, and limiting the result set.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
sort | query | string | No | Sort by field. Allowed values: cpu, memory, pid, name. Default: pid |
limit | query | integer | No | Maximum number of processes to return. Default: returns all |
filter | query | string | No | Filter by process name (substring match, case-insensitive) |
curl -X GET "https://api.hoody.com/api/v1/system/processes?sort=cpu&limit=10&filter=nginx" \ -H "Authorization: Bearer <token>"for await (const process of client.terminal.system.listProcessesIterator({ sort: "cpu", limit: 10, filter: "nginx"})) { console.log(process);}[ { "pid": 1234, "name": "nginx", "cpu_percent": 2.5, "memory_percent": 1.2, "state": "S", "command": "nginx: master process /usr/sbin/nginx" }, { "pid": 1235, "name": "nginx", "cpu_percent": 0.8, "memory_percent": 0.6, "state": "S", "command": "nginx: worker process" }]GET /api/v1/system/processes/{pid}
Section titled “GET /api/v1/system/processes/{pid}”Returns detailed information about a specific process, including all stats, cmdline, environment, and open files.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
pid | path | integer | Yes | Process ID |
curl -X GET https://api.hoody.com/api/v1/system/processes/1234 \ -H "Authorization: Bearer <token>"const proc = await client.terminal.system.getProcess({ pid: 1234 });{ "pid": 1234, "name": "nginx", "cmdline": "nginx: master process /usr/sbin/nginx -g daemon off;", "state": "S", "ppid": 1, "username": "root", "cpu_percent": 2.5, "memory_percent": 1.2, "memory_rss": 12582912, "memory_vms": 134217728, "create_time": "2025-01-15T08:00:00Z", "num_threads": 4}{ "statusCode": 404, "error": "Not Found", "message": "Process 99999 not found", "code": "PROCESS_NOT_FOUND"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROCESS_NOT_FOUND | Process does not exist | The requested PID is not running or has terminated | Check PID is valid and process is running |
Network Ports
Section titled “Network Ports”GET /api/v1/system/ports
Section titled “GET /api/v1/system/ports”Returns a JSON array of all TCP/UDP listening ports, including process information. Supports extensive filtering to narrow the result set.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
protocol | query | string | No | Filter by protocol: tcp, udp, or comma-separated list |
user | query | string | No | Filter by user (exact match) |
port | query | integer | No | Filter by specific port number |
ip | query | string | No | Filter by IP address (comma-separated list) |
skip_program | query | string | No | Exclude specific programs (comma-separated list) |
http_only | query | boolean | No | Only return HTTP services |
hoody_only | query | boolean | No | Only return Hoody Kit services |
curl -X GET "https://api.hoody.com/api/v1/system/ports?protocol=tcp&http_only=true&limit=50" \ -H "Authorization: Bearer <token>"for await (const port of client.terminal.system.listPortsIterator({ protocol: "tcp", http_only: true})) { console.log(port);}[ { "protocol": "tcp", "port": 22, "address": "0.0.0.0", "state": "LISTEN", "pid": 890, "process": "sshd", "user": "root" }, { "protocol": "tcp", "port": 80, "address": "0.0.0.0", "state": "LISTEN", "pid": 1234, "process": "nginx", "user": "www-data" }, { "protocol": "tcp", "port": 443, "address": "0.0.0.0", "state": "LISTEN", "pid": 1234, "process": "nginx", "user": "www-data" }]Process Signals
Section titled “Process Signals”POST /api/v1/system/process/signal
Section titled “POST /api/v1/system/process/signal”Send a Unix signal to one or more processes by PID or name. Supports all standard signals (SIGTERM, SIGKILL, SIGSTOP, SIGCONT, etc.). When targeting by name, the signal is sent to all matching processes.
This endpoint takes no path or query parameters.
Request Body
Section titled “Request Body”| Name | Type | Required | Description |
|---|---|---|---|
pid | integer | No | Process ID to signal (mutually exclusive with name) |
name | string | No | Process name to signal — signals ALL matching processes (mutually exclusive with pid) |
signal | string | integer | No | Signal to send. String form accepts SIGTERM, TERM, 15, etc. (with or without SIG prefix). Integer form accepts any value in [0, NSIG) including realtime signals SIGRTMIN..SIGRTMAX (typically 34..64 on Linux), which have no portable string names. |
force | boolean | No | Shorthand for SIGKILL (true) or SIGTERM (false) — overrides the signal parameter |
{ "pid": 1234, "signal": "SIGTERM"}curl -X POST https://api.hoody.com/api/v1/system/process/signal \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"pid": 1234, "signal": "SIGTERM"}'const result = await client.terminal.system.sendSignal({ data: { pid: 1234, signal: "SIGTERM" }});{ "success": true, "signal": "SIGTERM", "pid": 1234, "timestamp": "2025-01-15T10:30:00Z"}{ "statusCode": 400, "error": "Bad Request", "message": "Must specify pid or name", "code": "MISSING_TARGET"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TARGET | Must specify pid or name | Neither pid nor name was provided in the request body | Provide either pid or name parameter |
INVALID_SIGNAL | Invalid signal name | The signal value is not a recognized signal name or valid integer | Use valid signal (SIGTERM, SIGKILL, etc.) |
{ "statusCode": 403, "error": "Forbidden", "message": "No permission to signal process", "code": "PERMISSION_DENIED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PERMISSION_DENIED | No permission to signal process | The Hoody process does not have permission to signal the target process | Check process ownership |
{ "statusCode": 405, "error": "Method Not Allowed", "message": "Method GET not allowed", "allow": "POST"}{ "statusCode": 500, "error": "Internal Server Error", "message": "Failed to send signal", "code": "SIGNAL_FAILED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SIGNAL_FAILED | Failed to send signal | The signal could not be delivered to the target process | Check process exists |
System Power
Section titled “System Power”POST /api/v1/system/reboot
Section titled “POST /api/v1/system/reboot”Initiate a system reboot with optional delay. Requires root or sudo privileges — the Linux kernel enforces the permission check. Because shutdown(8) schedules in whole minutes, the server rounds the delay up to the nearest minute and reports the actual scheduled value as effective_minutes in the response.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
delay | query | integer | No | Delay in seconds before reboot, range 0..86400. Default: 0 (immediate) |
curl -X POST "https://api.hoody.com/api/v1/system/reboot?delay=60" \ -H "Authorization: Bearer <token>"const result = await client.terminal.system.reboot({ delay: 60 });{ "success": true, "effective_minutes": 1, "scheduled_at": "2025-01-15T10:31:00Z"}{ "statusCode": 400, "error": "Bad Request", "message": "Delay out of range (> 86400)", "code": "INVALID_DELAY"}{ "statusCode": 403, "error": "Forbidden", "message": "Reboot requires root privileges", "code": "ROOT_REQUIRED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
ROOT_REQUIRED | Reboot requires root privileges | The Hoody process is not running as root or with sudo | Run with sudo or as root user |
{ "statusCode": 405, "error": "Method Not Allowed", "message": "Method GET not allowed", "allow": "POST"}{ "statusCode": 500, "error": "Internal Server Error", "message": "Failed to execute reboot", "code": "REBOOT_FAILED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
REBOOT_FAILED | Failed to execute reboot | The shutdown command could not start the reboot sequence | Check system logs |
POST /api/v1/system/shutdown
Section titled “POST /api/v1/system/shutdown”Initiate a system shutdown with optional delay. Requires root or sudo privileges — the Linux kernel enforces the permission check. The delay is rounded up to the nearest minute by shutdown(8), and the actual scheduled value is reported as effective_minutes in the response.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
delay | query | integer | No | Delay in seconds before shutdown, range 0..86400. Default: 0 (immediate) |
curl -X POST "https://api.hoody.com/api/v1/system/shutdown?delay=300" \ -H "Authorization: Bearer <token>"const result = await client.terminal.system.shutdown({ delay: 300 });{ "success": true, "effective_minutes": 5, "scheduled_at": "2025-01-15T10:35:00Z"}{ "statusCode": 400, "error": "Bad Request", "message": "Delay out of range (> 86400)", "code": "INVALID_DELAY"}{ "statusCode": 403, "error": "Forbidden", "message": "Shutdown requires root privileges", "code": "ROOT_REQUIRED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
ROOT_REQUIRED | Shutdown requires root privileges | The Hoody process is not running as root or with sudo | Run with sudo or as root user |
{ "statusCode": 405, "error": "Method Not Allowed", "message": "Method GET not allowed", "allow": "POST"}{ "statusCode": 500, "error": "Internal Server Error", "message": "Failed to execute shutdown", "code": "SHUTDOWN_FAILED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SHUTDOWN_FAILED | Failed to execute shutdown | The shutdown command could not start the shutdown sequence | Check system logs |