The exec service provides endpoints for runtime health checks, performance monitoring, active request inspection, Prometheus metrics export, and graceful server restarts. Use these endpoints from your dashboards, alerting pipelines, and control-plane tooling to observe and manage a running exec instance.
Health
Section titled “Health”GET /api/v1/exec/health
Section titled “GET /api/v1/exec/health”Returns process-level health and metadata for the exec service, including build timestamp, process start time, resident memory, file descriptor count, process ID, peer IP, and the incoming User-Agent header.
This endpoint takes no parameters.
curl -X GET "https://exec.example.com/api/v1/exec/health"await client.exec.health.check();Response
{ "status": "ok", "service": "hoody-exec", "built": "2026-01-10T08:00:00.000Z", "started": "2026-01-15T00:00:00.000Z", "memory": { "rss": 178257920, "heap": 134217728 }, "fds": 42, "pid": 1234, "ip": "203.0.113.42", "userAgent": "curl/8.5.0"}{ "error": "Invalid request parameters", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "header", "reason": "missing or invalid header value" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "reason": "health probe failed" }}Performance Monitoring
Section titled “Performance Monitoring”GET /api/v1/exec/monitor/stats
Section titled “GET /api/v1/exec/monitor/stats”Returns process-wide counters: uptime, memory usage, cache sizes, request totals, WebSocket lifecycle counters, cron fire counts, and the count of dropped per-script metrics entries.
This endpoint takes no parameters.
curl -X GET "https://exec.example.com/api/v1/exec/monitor/stats"await client.exec.monitor.getStats();Response
{ "uptime": 86400, "memory": { "used": 134217728, "total": 268435456, "percentage": 50.0, "rss": 178257920, "external": 4194304 }, "cache": { "scripts": 12, "vms": 8, "sharedStates": 3, "activeWsHostnames": 2 }, "requests": { "total": 12453, "success": 12380, "errors": 73, "activeHttp": 2, "perSecond": 0.144, "per1m": 0.5, "per5m": 0.3, "per15m": 0.25 }, "websocket": { "opened": 87, "closed": 85, "active": 2, "normalCloses": 84, "abnormalCloses": 1 }, "cron": { "fires": 120, "errors": 2, "active": 0, "wrapperActive": 0 }, "droppedScripts": 0, "sinceMs": 1736899200000}{ "error": "Invalid request parameters", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "query", "reason": "unexpected parameter" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z"}GET /api/v1/exec/monitor/scripts
Section titled “GET /api/v1/exec/monitor/scripts”Lists all scripts tracked by the in-memory metrics registry, including HTTP/WS aggregate stats, recent errors, and lifecycle timestamps. Supports pagination via limit and ordering via sort.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | No | Max number of scripts to return. Clamped to [1, 500]. Default: 100. |
sort | query | string | No | Sort key. lastActivity (default) sorts by most recent activity; other keys sort descending by the matching metric. Accepted values: lastActivity, requests, errors, p95, ws_active. Default: "lastActivity". |
curl -X GET "https://exec.example.com/api/v1/exec/monitor/scripts?limit=50&sort=p95"await client.exec.monitor.listMonitorScripts({ limit: 50, sort: "p95"});Response
{ "count": 1, "total": 1, "scripts": [ { "scriptPath": "/api/hello", "hostname": "host-1", "vmCached": true, "sharedStateBytes": 1024, "activeHttp": 0, "activeWs": 2, "concurrentRunning": 1, "http": { "total": 1523, "success": 1510, "errors": 13, "meanDurationMs": 12.4, "p50DurationMs": 8.1, "p95DurationMs": 45.2, "maxDurationMs": 312.7 }, "ws": { "opened": 87, "closed": 85, "normalCloses": 84, "abnormalCloses": 1, "meanSessionMs": 12345, "maxSessionMs": 67890 }, "recentErrors": [ { "timestamp": "2026-01-15T10:25:00.000Z", "statusCode": 500, "message": "Unhandled exception in handler", "executionId": "exec_01HABCDEF1234567890ABCDEF" } ], "firstSeenAt": "2026-01-10T08:00:00.000Z", "lastActivityAt": "2026-01-15T10:30:00.000Z" } ]}{ "error": "Invalid query parameter", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "limit", "reason": "must be between 1 and 500" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z"}POST /api/v1/exec/monitor/script-performance
Section titled “POST /api/v1/exec/monitor/script-performance”Returns detailed lifetime metrics for a single tracked script, including per-script HTTP and WebSocket aggregates and a recent-duration sample array. The endpoint accepts an optional JSON body and returns an empty metrics object when no scriptPath is provided or the script is not tracked.
This endpoint takes no parameters.
Request Body
The request body is optional. The schema is empty {}; pass a payload to refine the response (the exact fields are not part of the public schema).
curl -X POST "https://exec.example.com/api/v1/exec/monitor/script-performance" \ -H "Content-Type: application/json" \ -d '{}'await client.exec.monitor.getScriptPerformance({});Response
{ "metrics": { "scriptPath": "/api/hello", "period": "lifetime", "http": { "total": 1523, "success": 1510, "errors": 13, "meanDurationMs": 12.4, "p50DurationMs": 8.1, "p95DurationMs": 45.2, "maxDurationMs": 312.7, "recentDurationsMs": [10, 12, 8, 45, 312, 9, 11, 7] }, "ws": { "opened": 87, "closed": 85, "normalCloses": 84, "abnormalCloses": 1, "meanSessionMs": 12345, "maxSessionMs": 67890 }, "activeHttp": 0, "activeWs": 2, "firstSeenAt": "2026-01-10T08:00:00.000Z", "lastActivityAt": "2026-01-15T10:30:00.000Z" }}{ "error": "Invalid request body", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "body", "reason": "malformed JSON" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z"}GET /api/v1/exec/monitor/metrics
Section titled “GET /api/v1/exec/monitor/metrics”Exposes runtime metrics in Prometheus 0.0.4 text exposition format, including per-script and global HTTP histograms, WebSocket connection gauges, error counters, and process_start_time_seconds.
This endpoint takes no parameters.
curl -X GET "https://exec.example.com/api/v1/exec/monitor/metrics"await client.exec.monitor.prometheusExport();Response
# HELP hoody_exec_http_requests_total Total HTTP requests served by scripts# TYPE hoody_exec_http_requests_total counterhoody_exec_http_requests_total{script="/api/hello",method="GET"} 1523hoody_exec_http_requests_total{script="/api/echo",method="POST"} 421
# HELP hoody_exec_http_errors_total Total HTTP errors served by scripts# TYPE hoody_exec_http_errors_total counterhoody_exec_http_errors_total{script="/api/hello",status="500"} 13
# HELP hoody_exec_http_duration_ms HTTP request duration in milliseconds (per-script histogram)# TYPE hoody_exec_http_duration_ms histogramhoody_exec_http_duration_ms_bucket{script="/api/hello",le="50"} 1480hoody_exec_http_duration_ms_bucket{script="/api/hello",le="100"} 1510hoody_exec_http_duration_ms_bucket{script="/api/hello",le="+Inf"} 1523hoody_exec_http_duration_ms_count{script="/api/hello"} 1523hoody_exec_http_duration_ms_sum{script="/api/hello"} 18855.2
# HELP hoody_exec_ws_connections_active Currently open WebSocket connections# TYPE hoody_exec_ws_connections_active gaugehoody_exec_ws_connections_active{script="/api/ws"} 2
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds# TYPE process_start_time_seconds gaugeprocess_start_time_seconds 1736899200{ "error": "Invalid request parameters", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "header", "reason": "invalid Accept header" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
# Prometheus exporter disabled (--prometheus off){ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z"}Active Requests
Section titled “Active Requests”GET /api/v1/exec/monitor/active-requests
Section titled “GET /api/v1/exec/monitor/active-requests”Returns the list of in-flight script HTTP requests currently being handled, including execution ID, script path, method, URL (with tokens redacted), start time, and elapsed duration in milliseconds.
This endpoint takes no parameters.
curl -X GET "https://exec.example.com/api/v1/exec/monitor/active-requests"await client.exec.monitor.getActiveRequests();Response
{ "count": 2, "active": [ { "executionId": "exec_01HABCDEF1234567890ABCDEF", "scriptPath": "/api/hello", "hostname": "host-1", "clientIp": "203.0.113.42", "method": "GET", "url": "/api/hello?token=***", "startedAt": "2026-01-15T10:30:00.000Z", "duration": 125 }, { "executionId": "exec_01HIJKLMN1234567890ABCDEF", "scriptPath": "/api/echo", "hostname": "host-1", "clientIp": "198.51.100.7", "method": "POST", "url": "/api/echo", "startedAt": "2026-01-15T10:30:02.000Z", "duration": 42 } ]}{ "error": "Invalid request parameters", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "query", "reason": "unexpected parameter" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z"}System Management
Section titled “System Management”GET /api/v1/exec/system/restart-status
Section titled “GET /api/v1/exec/system/restart-status”Reports whether the server can be safely restarted right now. Returns current uptime, the count of in-flight script requests, and a restartReady flag derived from those inputs.
This endpoint takes no parameters.
curl -X GET "https://exec.example.com/api/v1/exec/system/restart-status"await client.exec.system.getRestartStatus();Response
{ "canRestart": true, "uptime": 86400, "uptimeFormatted": "1d 0h 0m", "activeRequests": 0, "active": [], "restartReady": true}{ "error": "Invalid request parameters", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "query", "reason": "unexpected parameter" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z"}POST /api/v1/exec/system/restart
Section titled “POST /api/v1/exec/system/restart”Triggers a server restart. In graceful mode the server drains in-flight requests up to drainTimeoutMs before exiting; the non-graceful path performs an immediate restart.
This endpoint takes no parameters.
Request Body
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
graceful | boolean | No | true | Drain in-flight requests before restarting. |
drainTimeoutMs | integer | No | 5000 | Maximum time in milliseconds to wait for in-flight requests to complete during a graceful restart. |
reason | string | No | "API restart request" | Free-form reason recorded in server logs. |
curl -X POST "https://exec.example.com/api/v1/exec/system/restart" \ -H "Content-Type: application/json" \ -d '{ "graceful": true, "drainTimeoutMs": 10000, "reason": "deploying v1.2.3" }'await client.exec.system.restartServer({ graceful: true, drainTimeoutMs: 10000, reason: "deploying v1.2.3"});Response
{ "error": "Invalid restart options", "code": "VALIDATION_ERROR", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "field": "drainTimeoutMs", "reason": "must be a positive integer" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Internal server error", "code": "ERROR_500", "timestamp": "2026-01-15T10:30:00.000Z", "details": { "reason": "restart handler unavailable" }}