Dash HTTP API
Base path:
/api
Error format:
{ "code": "<string>", "message": "<string>" }
Request Conventions
- All
/apiresponses, including authentication and routing errors, carryCache-Control: no-store. The API body limit is 24 MiB, with smaller limits on some endpoints; size limits apply when a body is read. - Method names are case-sensitive. Dash implements GET, HEAD, POST, PUT, PATCH, and DELETE. Other methods, including OPTIONS and lowercase
get, return501 not_implemented. Implemented methods return404 not_foundfor unknown paths or405 method_not_allowedwithAllowwhen an existing endpoint does not accept the method. GET APIs do not imply HEAD. /api/version/and admin module roots listed below also accept their forms without a trailing slash, without redirects. Node-ID PATCH and DELETE paths also accept trailing slashes; other endpoints do not automatically gain aliases.- JSON requests require a valid
application/jsonmedia type; valid parameters are allowed. Invalid media types or parameters return415 unsupported_media_type. - JSON field names are case-sensitive. Unknown fields are ignored unless an endpoint specifies stricter validation. Duplicate object keys and invalid UTF-8 are rejected. Clients must not depend on response whitespace, object-key order, or HTML-character escaping.
- Node metrics must finish persistence within 5 seconds of server receipt. Authentication, body reading, and node-lock waits consume that budget. Expired reports return
503 service_unavailablewithout persisting metrics.
Authentication
| Method | Use |
|---|---|
| Admin password | POST /api/auth/login |
refresh cookie + X-CSRF-Token | POST /api/auth/refresh, POST /api/auth/logout |
Authorization: Bearer <access_token> | Admin APIs and optionally authenticated reads |
X-Node-Secret | Node reporting, node identity reads, and deploy asset downloads |
upgrade_token query | Temporary deploy asset download grant issued only for legacy Node upgrades |
Public and Optional Auth
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /api/version/ | None | Dash and bundled node version |
GET | /api/front/brand | Optional Bearer | Brand info |
GET | /api/front/metrics | Optional Bearer | Current front metrics |
GET | /api/front/groups | Optional Bearer | Front groups |
GET | /api/metrics/online | Optional Bearer | Online rate |
GET | /api/metrics/uptime | Optional Bearer | Uptime for the latest 45 calendar days |
GET | /api/metrics/uptime/day | Optional Bearer | 24 hourly rates for one calendar day |
GET | /api/metrics/history | Optional Bearer | History metrics |
GET | /api/statistics/access | Optional Bearer | Anonymous access settings |
GET | /api/statistics/traffic/settings | Optional Bearer | Traffic settings |
GET | /api/statistics/traffic/ifaces | Optional Bearer | Node interface list |
GET | /api/statistics/traffic/summary | Optional Bearer | Current billing cycle traffic |
GET | /api/statistics/traffic/daily | Optional Bearer | Daily traffic, requires billing mode |
GET | /api/statistics/traffic/monthly | Optional Bearer | Monthly traffic |
Optional Bearer endpoints treat invalid Bearer tokens as anonymous requests.
GET /api/statistics/traffic/ifaces?server_id=<id> returns interface names previously reported by the node. Results are ordered by latest sample time, with actively reporting interfaces first; equal timestamps are ordered by interface name. Historical interfaces remain listed for querying older traffic data.
Node Uptime
GET /api/metrics/uptime(also with a trailing slash) returns{enabled, timezone, generated_at, warning_sla, error_sla, nodes}. Each node has a stringserver_idand 45days, oldest first including today. Each day hasdate(YYYY-MM-DD),percent(0–100 ornull), andobserved_ms(observed milliseconds). Dates followapp.timezone, or the server's local timezone when unset. All dates are present even when no observations exist.- Authenticated callers receive all non-deleted nodes. Guests receive only guest-visible nodes when
uptime_guest_visibleis enabled; otherwise the daily endpoint returns200withenabled: falseand an empty node list. SLA thresholds come from system settings and do not affect sampling. GET /api/metrics/uptime/day?server_id=<id>&date=YYYY-MM-DD(also/day/) returns{date, hours, observed_ms}. Both arrays have 24 entries indexed by local clock hour. Missing or future hours have anullpercentage and zero observed milliseconds. On a daylight-saving transition, a skipped hour is unknown and repeated clock hours combine their durations. Disabled guest access returns403 forbidden; hidden, deleted, and absent nodes return404 not_foundto guests. Invalid IDs or dates outside the same 45-day window return400 invalid_request; database failures return503 service_unavailable.- Percentages are
100 × online milliseconds / observed milliseconds, weighted by duration. A report covers the interval from its server receive time untilapp.node_offline_thresholdlater; overlapping intervals count once. The first current-metrics row starts the node's observation window. Only completed minutes are included, normally finalized six seconds after each minute boundary; current-day and current-hour values can lag by about one minute plus that delay. Missing minutes are unknown and excluded from the denominator. A percentage is not proof of complete coverage;observed_msreports how much was observed. The existing/api/metrics/onlineretains its previous contract and data source. - The dashboard refreshes daily uptime independently every 60 seconds, and loads hour details only for an expanded day. Disabling guest access hides uptime; logging out discards authenticated uptime state.
Auth Sessions
POST /api/auth/login request bodies must include password and persistence. persistence allows session or persistent. Successful responses include access_token, expires_at, and csrf_token, and set refresh/CSRF cookies. Malformed login JSON returns 400 invalid_json, invalid persistence returns 400 invalid_persistence, and login rate limiting returns 429 rate_limited.
| Method | Path | Auth | Success |
|---|---|---|---|
POST | /api/auth/login | Admin password | 200 |
POST | /api/auth/refresh | refresh cookie + X-CSRF-Token | 200 |
POST | /api/auth/logout | refresh cookie + X-CSRF-Token | 204 |
GET | /api/auth/sessions/ | Bearer | 200 |
DELETE | /api/auth/sessions/current | Bearer | 204 |
DELETE | /api/auth/sessions/ | Bearer | 204 |
DELETE | /api/auth/sessions/{sid} | Bearer | 204 |
GET /api/auth/sessions/ returns { "sessions": [...] } for the bearer token user. Each item includes id, expires_at, session_only, and current.
Node Endpoints
| Method | Path | Auth | Body | Success |
|---|---|---|---|---|
POST | /api/node/identity | X-Node-Secret | {} | 200 |
POST | /api/node/metrics | X-Node-Secret | NodeReport | 200 |
POST | /api/node/static | X-Node-Secret | Static | 200 |
Successful /api/node/metrics response:
{
"ok": true,
"update": null
}
Or:
{
"ok": true,
"update": {
"id": "release-id",
"version": "1.2.3",
"url": "https://dash.example.com/deploy/windows/node_windows_amd64.exe?upgrade_token=...",
"sha256": "...",
"size": 12345678
}
}
url may include a short-lived upgrade_token so legacy Nodes can download the exact update asset without sending X-Node-Secret. Clients must use the returned URL unchanged.
Pending upgrade tasks are volatile and clear when Node reports the exact target version or a higher SemVer precedence. Different build metadata at the same SemVer precedence is treated as a distinct Node binary and can still be delivered.
Admin: Groups
| Method | Path | Body | Success |
|---|---|---|---|
GET | /api/admin/groups/ | None | 200 |
GET | /api/admin/groups/map | None | 200 |
POST | /api/admin/groups/ | { "name": "...", "remark": "..." } | 204 |
PATCH | /api/admin/groups/{id} | { "name": "...", "remark": "..." } | 204 |
DELETE | /api/admin/groups/{id} | None | 204 |
Group name is trimmed, contains 1–64 Unicode characters, and cannot contain control characters. remark is trimmed, limited to 255 Unicode characters, and cannot contain control characters.
Admin: Nodes
| Method | Path | Body | Success |
|---|---|---|---|
GET | /api/admin/nodes/ | None | 200 |
GET | /api/admin/nodes/deploy | None | 200 |
POST | /api/admin/nodes/ | None | 204 |
PUT | /api/admin/nodes/display-order | Node ID order | 204 |
PATCH | /api/admin/nodes/traffic-p95 | { "ids": [1, 2], "enabled": true } | 204 |
PATCH | /api/admin/nodes/{id} | Node patch | 204 |
POST | /api/admin/nodes/{id}/upgrade | None | 204 |
GET | /api/admin/nodes/traffic/rebuild | None | 200 |
POST | /api/admin/nodes/{id}/traffic/rebuild | None | 202 |
DELETE | /api/admin/nodes/{id} | None | 204 |
Node patch fields:
{
"name": "node-a",
"is_guest_visible": true,
"traffic_p95_enabled": true,
"traffic_cycle_mode": "calendar_month",
"traffic_billing_start_day": 1,
"traffic_billing_anchor_date": "",
"traffic_billing_timezone": "Asia/Shanghai",
"traffic_direction_mode": "default",
"display_order": 1,
"tags": ["prod", "hk"],
"secret": "new-secret",
"group_ids": [1, 2]
}
Node names are trimmed, contain 1–64 Unicode characters, and cannot contain control characters. tags allows at most 32 items; each trimmed item is limited to 64 Unicode characters and cannot contain control characters. Empty and duplicate values are removed.
When reading stored tags, Dash logs a warning and drops invalid or excess items. Unparseable stored JSON becomes an empty tag list without dropping the node's other metrics from the frontend projection.
After trimming, secret must contain 8–128 Unicode characters. Invalid values return 400 invalid_secret; a value owned by another node returns 409 duplicate_secret.
Node billing cycle fields are atomic. If any cycle field is submitted, the request must include traffic_cycle_mode and every field required by that mode. Stored modes are calendar_month, whmcs_compatible, and clamp_to_month_end. Legacy default is accepted only without other cycle fields and is stored as an explicit calendar month.
traffic_direction_mode allows default, out, both, and max. default inherits the global direction mode; other values override that node.
/api/admin/nodes/traffic-p95 accepts ids and enabled. enabled is required. ids must be a non-empty positive integer array, cannot contain duplicates, and can contain at most 10000 items. The command validates all node IDs first, then updates them in one transaction. Success returns 204; any missing or deleted node returns 404 not_found, and no node is updated.
GET /api/admin/nodes/traffic/rebuild returns the latest process-local rebuild task state. Before any task exists it returns status=idle; running responses include server_id, running=true, and started_at; finished responses may return completed or failed until replaced by the next task. This state is not durable across process restarts. Failed states expose stable code and error values, not internal error strings.
POST /api/admin/nodes/{id}/traffic/rebuild is Billing-only. It rewrites 5-minute facts in 6-hour chunks and invalidates overlapping snapshots. Lite mode returns 409 traffic_rebuild_requires_billing; a running task returns 409 traffic_rebuild_running; unavailable execution returns 503 traffic_rebuild_unavailable. Switching to Lite lets the current chunk finish, then stops the job.
GET /api/admin/nodes/ field version.supports_auto_update shows whether the current node version meets the Dash admin console automatic update delivery requirement. The minimum version is 0.2.3.
POST /api/admin/nodes/{id}/upgrade requires version.supports_auto_update=true. Current node versions below 0.2.3 return 409 node_upgrade_unsupported; unavailable bundled versions, platforms, or assets return 409; failure to prepare the legacy temporary download grant returns 503 node_upgrade_grant_error.
Admin: Traffic Settings
| Method | Path | Body | Success |
|---|---|---|---|
PATCH | /api/statistics/traffic/settings | Partial fields | 204 |
Fields are documented in Traffic Accounting and Billing Cycles.
Only guest_access_mode, usage_mode, and direction_mode are writable. Sending a global billing-cycle field returns 400 billing_cycle_is_per_node.
Traffic Queries
GET /api/statistics/traffic/dailyrequiresusage_mode=billing; otherwise it returns409 traffic_daily_requires_billing.periodallowscurrentorprevious; omitted meanscurrent.GET /api/statistics/traffic/monthlysupportsmonthsin1..24andperiod=current|previous.- Traffic queries use each node's explicit billing cycle. Only
traffic_direction_mode=defaultinherits the global direction. - Traffic summary, daily, and monthly responses keep raw
in_*andout_*fields. The active accounting view is exposed throughselected_bytes,selected_p95_bytes_per_sec,selected_peak_bytes_per_sec, and selected direction fields. - Clients use
data_complete,coverage_ratio,gap_count, andreset_count. The deprecatedpartialfield has been removed.
History Metrics
GET /api/front/metrics node objects can include node.tags, disk.smart, disk.temperature_devices[], top-level thermal, and top-level pressure. SMART, thermal, and pressure runtime payloads are cached separately from the front node snapshot and are reattached only when received_at matches.
GET /api/metrics/history supports temperature metrics:
| Metric | Source | Device parameter |
|---|---|---|
cpu.temp_c | Maximum CPU thermal sensor temperature | Not required |
disk.temp_c | SMART physical disk temperature history | Optional; omitting it aggregates physical-disk rows |
For disk.temp_c, device can match physical disk name, ref, or path.
Disk temperature history is written only for backend-confirmed physical disks. Virtual disks and RAID devices are not persisted as disk.temp_c.
GET /api/metrics/history also supports PSI average metrics:
pressure.cpu.some_avg10,pressure.cpu.some_avg60,pressure.cpu.some_avg300pressure.memory.some_avg10,pressure.memory.some_avg60,pressure.memory.some_avg300pressure.memory.full_avg10,pressure.memory.full_avg60,pressure.memory.full_avg300pressure.io.some_avg10,pressure.io.some_avg60,pressure.io.some_avg300pressure.io.full_avg10,pressure.io.full_avg60,pressure.io.full_avg300
History ranges select a fixed data source while HTTP parameters, response fields, point counts, and ordering remain unchanged:
range | Source | Point interval |
|---|---|---|
30m, 1h, 12h, 24h | Raw samples | 3 seconds, 6 seconds, 60 seconds, 120 seconds |
1w | 15-minute aggregate | 15 minutes |
15d | Weighted re-aggregation of 15-minute data | 30 minutes |
30d | One-hour aggregate | One hour |
Temperature and exposed PSI averages use the same aggregate model as other regular metrics. Aggregate queries include the latest raw samples. Exact sample points remain available during the configured raw retention period, which defaults to eight days. Fifteen-minute and one-hour aggregate results remain available for 16 and 32 days, respectively.
Admin: Alerts
| Method | Path | Description |
|---|---|---|
GET | /api/admin/alerts/rules/ | List rules |
POST | /api/admin/alerts/rules/ | Create rule |
PATCH | /api/admin/alerts/rules/{id} | Update rule |
DELETE | /api/admin/alerts/rules/{id} | Delete rule |
GET | /api/admin/alerts/mounts/ | List mounts |
PUT | /api/admin/alerts/mounts/ | Set mounts |
GET | /api/admin/alerts/settings/ | Read global settings |
PUT | /api/admin/alerts/settings/ | Replace global settings |
GET | /api/admin/alerts/events/ | List alert records |
GET | /api/admin/alerts/events/summary | List open alert summaries |
GET | /api/admin/alerts/events/servers | List alert-record filter nodes |
GET | /api/admin/alerts/channels/ | List channels |
POST | /api/admin/alerts/channels/ | Create channel |
GET | /api/admin/alerts/channels/{id} | Read channel |
PUT | /api/admin/alerts/channels/{id} | Replace channel |
PUT | /api/admin/alerts/channels/{id}/enabled | Toggle enabled |
POST | /api/admin/alerts/channels/{id}/test | Send test notification |
DELETE | /api/admin/alerts/channels/{id} | Delete channel |
POST | /api/admin/alerts/channels/telegram/mtproto/code | Start MTProto login and send a code |
POST | /api/admin/alerts/channels/telegram/mtproto/verify | Verify the login code |
POST | /api/admin/alerts/channels/telegram/mtproto/password | Submit the two-step verification password |
POST | /api/admin/alerts/channels/telegram/mtproto/ping | Check the stored MTProto session |
GET /api/admin/alerts/events/ supports server_id, status=open|closed|all, metric, from, to, cursor, and limit. from and to use RFC3339. limit defaults to 200 and is capped at 500. The default status is open.
Alert record responses include items, next_cursor, and has_more. Each item includes node, rule, metric, status, first trigger time, last trigger time, close time, current value, effective threshold, and close reason.
Channel reads include delivery health, retry/probe times, and pending/blocked counts. Invalid stored channels remain visible with config=null and can only be deleted. MTProto login-state failures return 503 login_state_error; concurrent revision changes return 409 channel_changed.
Admin: System
| Method | Path | Description |
|---|---|---|
GET | /api/admin/system/settings/ | Read system settings |
PUT | /api/admin/system/settings/ | Replace system settings |
PATCH | /api/admin/system/settings/ | Partial update |
GET | /api/admin/system/dash-update/status | Read Dash updater status |
GET | /api/admin/system/dash-update/check | Check Dash updates |
POST | /api/admin/system/dash-update/run | Start a Dash update task |
GET | /api/admin/system/dash-update/release-notes | Read Release Notes HTML |
GET | /api/admin/system/themes/ | List themes |
POST | /api/admin/system/themes/upload | Upload theme zip |
POST | /api/admin/system/themes/{id}/apply | Apply theme |
DELETE | /api/admin/system/themes/{id} | Delete theme |
System settings include history_guest_access_mode, dash_update_channel, dash_update_mode, logo_url, page_title, topbar_text, uptime_guest_visible, uptime_warning_sla, and uptime_error_sla. PATCH accepts partial updates. PUT requires the first six fields.
uptime_guest_visible defaults to true. Warning and error thresholds default to 99 and 95, allow decimals, and must satisfy 0 <= error < warning <= 100. Omitted or null uptime fields retain their previous values in both PATCH and PUT. Invalid thresholds return 400 invalid_fields and roll back the whole update. These settings control access and presentation without changing sampling.
New logo_url values accept same-origin absolute paths, supported base64 image data URLs, or external HTTPS URLs. Stored external HTTP logos remain readable; a PATCH for other fields does not revalidate an omitted logo.
dash_update_channel allows release or prerelease. dash_update_mode allows manual, notify, or auto.
GET /api/admin/system/dash-update/check returns the target version and opaque install_revision. POST /run accepts action=update|reinstall, channel, lang, and the immutable plan fields from the check response. A stale plan finishes with failure_code=install_changed and never selects another target.
Update jobs and transactions persist under $DASH_HOME/runtime/dash-update. failure_code=recovery_required requires root to run dash update recover.