Skip to content

Uptime Monitor

HTTP and TCP uptime checks with alerting.

All endpoints below are mounted under /api. Authentication: Authorization: Bearer <token> unless noted as public.

Endpoint count: 8

Endpoints

Method Path Handler Guards
GET /api/uptime/monitors listUptimeMonitors RequireSuperuser()
POST /api/uptime/monitors createUptimeMonitor RequireSuperuser()
DELETE /api/uptime/monitors/:id deleteUptimeMonitor RequireSuperuser()
PUT /api/uptime/monitors/:id updateUptimeMonitor RequireSuperuser()
POST /api/uptime/monitors/:id/check manualUptimeCheck RequireSuperuser()
GET /api/uptime/monitors/:id/history getUptimeHistory RequireSuperuser()
POST /api/uptime/monitors/:id/toggle toggleUptimeMonitor RequireSuperuser()
GET /api/uptime/status getUptimeStatus RequireSuperuser()

Source

Handlers for this section live in api/routes/handlers_*.go in the StarkOne source. Each handler binds its request body with gin.ShouldBindJSON(&req) and responds with the standard envelope:

{ "data": { ... } }

On error:

{ "error": { "code": "string", "message": "string" } }

Note: the uptime handlers emit error bodies as { "error": { "message": "..." } } without a code field. The code key shown above is the panel-wide convention; it is not populated by these specific handlers.

Reference

GET /api/uptime/monitors

Lists all configured uptime monitors with their full configuration and last-check state, ordered by creation time (newest first).

Guards: RequireSuperuser()

Response - 200 OK

{
  "data": {
    "monitors": [
      {
        "id": 1,
        "name": "Main site",
        "type": "http",
        "target": "https://example.com",
        "http_method": "GET",
        "http_override_ip": "",
        "http_keyword": "",
        "http_skip_ssl": false,
        "check_interval": 300,
        "timeout": 5,
        "alert_email": "[email protected]",
        "alert_webhook": "",
        "webhook_skip_ssl": false,
        "alert_ai": false,
        "is_enabled": true,
        "is_down": false,
        "last_check": "2026-06-17 12:00:00",
        "last_status": 200,
        "last_response_time": 142,
        "last_error": "",
        "fail_count": 0,
        "total_checks": 288,
        "created_at": "2026-06-01 09:00:00",
        "dns_failover": false,
        "dns_zone": "",
        "dns_record_name": "",
        "dns_record_type": "A",
        "dns_up_ip": "",
        "dns_down_ip": ""
      }
    ]
  }
}

If the Uptime Monitor plugin is not installed (the uptime_monitors table does not exist), the handler returns 200 OK with an empty list: { "data": { "monitors": [] } }.

Errors

Status Code Meaning
500 - Database query failed ({ "error": { "message": "..." } }).

Side effects

  • Calls ensureUptimeMonitorSchema(db), which may run schema/migration DDL on the uptime_monitors table to add missing columns.

Example

curl -X GET https://panel.example.com:2087/api/uptime/monitors \
  -H "Authorization: Bearer $TOKEN"

POST /api/uptime/monitors

Creates a new uptime monitor from the request body, applying defaults for method, interval, timeout, and DNS record type.

Guards: RequireSuperuser()

Request body

{
  "name": "string (required)",
  "type": "string (required)",
  "target": "string (required)",
  "http_method": "string (optional, default GET)",
  "http_override_ip": "string (optional)",
  "http_keyword": "string (optional)",
  "http_skip_ssl": "bool (optional)",
  "check_interval": "int (optional, default 300)",
  "timeout": "int (optional, default 5)",
  "alert_email": "string (optional)",
  "alert_webhook": "string (optional)",
  "webhook_skip_ssl": "bool (optional)",
  "alert_ai": "bool (optional)",
  "dns_failover": "bool (optional)",
  "dns_zone": "string (optional)",
  "dns_record_name": "string (optional)",
  "dns_record_type": "string (optional, default A)",
  "dns_up_ip": "string (optional)",
  "dns_down_ip": "string (optional)"
}
Field Type Required Description
name string yes Display name of the monitor.
type string yes Monitor type (e.g. http, tcp); not validated against an enum in the handler.
target string yes URL or host:port to check.
http_method string no HTTP method for HTTP checks. Defaults to GET when empty.
http_override_ip string no IP to connect to instead of resolving the target host.
http_keyword string no Keyword that must be present in the response body.
http_skip_ssl bool no Skip TLS certificate verification.
check_interval int no Seconds between checks. Defaults to 300 when 0.
timeout int no Per-check timeout in seconds. Defaults to 5 when 0.
alert_email string no Email address for down/up alerts.
alert_webhook string no Webhook URL for alerts.
webhook_skip_ssl bool no Skip TLS verification when posting to the webhook.
alert_ai bool no Send alerts to the AI agent.
dns_failover bool no Enable DNS failover behavior.
dns_zone string no DNS zone for failover.
dns_record_name string no DNS record name for failover.
dns_record_type string no DNS record type. Defaults to A when empty.
dns_up_ip string no IP to set when the target is up.
dns_down_ip string no IP to set when the target is down.

Response - 200 OK

{ "data": { "id": 2, "message": "Monitor created" } }

Errors

Status Code Meaning
400 - Uptime Monitor plugin not installed, or request body failed binding (e.g. missing required field).
500 - Database insert failed.

Side effects

  • Inserts a row into the uptime_monitors table.

Example

curl -X POST https://panel.example.com:2087/api/uptime/monitors \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Main site", "type": "http", "target": "https://example.com"}'

DELETE /api/uptime/monitors/:id

Deletes a monitor and all of its history records.

Guards: RequireSuperuser()

Path parameters

Name Type Description
id int ID of the monitor to delete.

Response - 200 OK

{ "data": { "message": "Monitor deleted" } }

Side effects

  • Deletes rows from uptime_monitor_history (matching monitor_id) and from uptime_monitors. Errors from these statements are not surfaced; the handler always returns success.

Example

curl -X DELETE https://panel.example.com:2087/api/uptime/monitors/2 \
  -H "Authorization: Bearer $TOKEN"

PUT /api/uptime/monitors/:id

Updates all configuration fields of an existing monitor and bumps its updated_at timestamp.

Guards: RequireSuperuser()

Path parameters

Name Type Description
id int ID of the monitor to update.

Request body

{
  "name": "string (optional)",
  "type": "string (optional)",
  "target": "string (optional)",
  "http_method": "string (optional)",
  "http_override_ip": "string (optional)",
  "http_keyword": "string (optional)",
  "http_skip_ssl": "bool (optional)",
  "check_interval": "int (optional)",
  "timeout": "int (optional)",
  "alert_email": "string (optional)",
  "alert_webhook": "string (optional)",
  "webhook_skip_ssl": "bool (optional)",
  "alert_ai": "bool (optional)",
  "dns_failover": "bool (optional)",
  "dns_zone": "string (optional)",
  "dns_record_name": "string (optional)",
  "dns_record_type": "string (optional)",
  "dns_up_ip": "string (optional)",
  "dns_down_ip": "string (optional)"
}
Field Type Required Description
name string no Display name.
type string no Monitor type.
target string no URL or host:port to check.
http_method string no HTTP method. No default is applied on update.
http_override_ip string no IP to connect to instead of resolving the host.
http_keyword string no Required response-body keyword.
http_skip_ssl bool no Skip TLS certificate verification.
check_interval int no Seconds between checks. No default is applied on update.
timeout int no Per-check timeout in seconds. No default is applied on update.
alert_email string no Alert email address.
alert_webhook string no Alert webhook URL.
webhook_skip_ssl bool no Skip TLS verification for the webhook.
alert_ai bool no Send alerts to the AI agent.
dns_failover bool no Enable DNS failover.
dns_zone string no DNS zone for failover.
dns_record_name string no DNS record name.
dns_record_type string no DNS record type. No default is applied on update.
dns_up_ip string no IP when up.
dns_down_ip string no IP when down.

All fields are sent to the UPDATE statement regardless of whether they were present in the request. Omitted fields default to their Go zero value and overwrite the stored value, so callers should send the complete configuration.

Response - 200 OK

{ "data": { "message": "Monitor updated" } }

Errors

Status Code Meaning
400 - Request body failed binding.
500 - Database update failed.

Side effects

  • Updates the matching row in uptime_monitors and sets updated_at = CURRENT_TIMESTAMP. A non-existent id produces no error (zero rows affected) and still returns success.

Example

curl -X PUT https://panel.example.com:2087/api/uptime/monitors/2 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Main site", "type": "http", "target": "https://example.com", "check_interval": 60, "timeout": 10}'

POST /api/uptime/monitors/:id/check

Triggers an immediate, asynchronous health check for a single monitor.

Guards: RequireSuperuser()

Path parameters

Name Type Description
id int ID of the monitor to check.

Response - 200 OK

{ "data": { "message": "Check triggered" } }

Errors

Status Code Meaning
404 - Monitor not found ({ "error": { "message": "Monitor not found" } }).

Side effects

  • Loads the monitor config from uptime_monitors, then runs performUptimeCheck(...) in a background goroutine. That check performs the HTTP/TCP probe and may update the monitor's status columns, write a history row, and dispatch email/webhook/AI alerts and DNS failover updates. The HTTP response returns immediately and does not reflect the check result.

Example

curl -X POST https://panel.example.com:2087/api/uptime/monitors/2/check \
  -H "Authorization: Bearer $TOKEN"

GET /api/uptime/monitors/:id/history

Returns recent check-history events for a monitor, newest first.

Guards: RequireSuperuser()

Path parameters

Name Type Description
id int ID of the monitor whose history is returned.

Query parameters

Name Type Optional Description
limit int yes Maximum number of history rows to return. Defaults to 100.

Response - 200 OK

{
  "data": {
    "history": [
      {
        "id": 10,
        "event_type": "down",
        "status": 503,
        "response_time": 0,
        "error": "connection refused",
        "created_at": "2026-06-17 11:55:00"
      }
    ]
  }
}

Errors

Status Code Meaning
500 - Database query failed.

Example

curl -X GET "https://panel.example.com:2087/api/uptime/monitors/2/history?limit=50" \
  -H "Authorization: Bearer $TOKEN"

POST /api/uptime/monitors/:id/toggle

Flips a monitor's enabled state (enabled to disabled, or vice versa).

Guards: RequireSuperuser()

Path parameters

Name Type Description
id int ID of the monitor to toggle.

Response - 200 OK

{ "data": { "message": "Monitor toggled" } }

Side effects

  • Runs UPDATE uptime_monitors SET is_enabled = 1 - is_enabled, updated_at = CURRENT_TIMESTAMP WHERE id = ?. The exec error is not checked; a non-existent id still returns success.

Example

curl -X POST https://panel.example.com:2087/api/uptime/monitors/2/toggle \
  -H "Authorization: Bearer $TOKEN"

GET /api/uptime/status

Returns aggregate counts of enabled monitors by state (up, down, warning) plus install/running status.

Guards: RequireSuperuser()

Response - 200 OK

{
  "data": {
    "installed": true,
    "running": true,
    "total": 5,
    "up": 4,
    "down": 1,
    "warning": 0
  }
}

When the plugin is not installed, the handler returns { "data": { "installed": false } } only. Counts are over enabled monitors only: up = not down and empty last_error, down = is_down = 1, warning = not down but non-empty last_error. running reflects the in-process uptimeMonitorRunning flag.

Example

curl -X GET https://panel.example.com:2087/api/uptime/status \
  -H "Authorization: Bearer $TOKEN"