mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-10-28 07:41:27 +00:00
Structured DNSRecord list carries the detected vendor per row (NS/MX/CNAME/ TXT value, ASN org, response headers, SPF includes, verification strings) and a Providers strip shows registrar/DNS/hosting/email/CA with favicons — the domainstack-style view. Detection tables expanded to ~70 NS, ~45 mail, ~60 CNAME, ~130 registrar, and ~50 TXT patterns. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2193 lines
57 KiB
YAML
2193 lines
57 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Dash API
|
|
version: 0.1.0
|
|
description: >
|
|
Single source of truth for the Dash API. The TypeScript client in
|
|
packages/api-client is generated from this file — do not hand-write
|
|
API types in the frontend.
|
|
servers:
|
|
- url: /
|
|
paths:
|
|
/api/healthz:
|
|
get:
|
|
operationId: healthz
|
|
summary: Liveness + database reachability probe
|
|
responses:
|
|
"200":
|
|
description: Service healthy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Health"
|
|
"503":
|
|
description: Database unreachable
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Health"
|
|
|
|
/api/boards:
|
|
get:
|
|
operationId: listBoards
|
|
summary: All boards, ordered
|
|
responses:
|
|
"200":
|
|
description: Board list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Board"
|
|
post:
|
|
operationId: createBoard
|
|
summary: Create a board — slug derived from the name
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
responses:
|
|
"201":
|
|
description: Created board
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Board"
|
|
|
|
/api/boards/{id}:
|
|
patch:
|
|
operationId: updateBoard
|
|
summary: Rename a board — the slug stays stable
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Updated board
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Board"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteBoard
|
|
summary: Delete a board and its sections — the last board cannot be deleted
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/sections:
|
|
get:
|
|
operationId: listSections
|
|
summary: Board tree — sections with nested items and urls, ordered
|
|
parameters:
|
|
- name: board
|
|
in: query
|
|
description: Restrict to one board id; omitted returns all sections
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Ordered board tree
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Section"
|
|
post:
|
|
operationId: createSection
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SectionInput"
|
|
responses:
|
|
"201":
|
|
description: Created section
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Section"
|
|
|
|
/api/sections/{id}:
|
|
patch:
|
|
operationId: updateSection
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SectionPatch"
|
|
responses:
|
|
"200":
|
|
description: Updated section
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Section"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteSection
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"204":
|
|
description: Section and its items deleted
|
|
|
|
/api/sections/reorder:
|
|
post:
|
|
operationId: reorderSection
|
|
summary: Move a section between two neighbors (fractional position)
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Reorder"
|
|
responses:
|
|
"200":
|
|
description: Reordered
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Section"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/items:
|
|
post:
|
|
operationId: createItem
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ItemInput"
|
|
responses:
|
|
"201":
|
|
description: Created item
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Item"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/items/{id}:
|
|
patch:
|
|
operationId: updateItem
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ItemPatch"
|
|
responses:
|
|
"200":
|
|
description: Updated item
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Item"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteItem
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"204":
|
|
description: Item deleted
|
|
|
|
/api/items/{id}/icon:
|
|
post:
|
|
operationId: uploadIcon
|
|
summary: Upload an icon file; returns the stored icon reference
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file]
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
responses:
|
|
"200":
|
|
description: Icon stored
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Item"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/items/reorder:
|
|
post:
|
|
operationId: reorderItem
|
|
summary: Move an item between two neighbors, optionally across sections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ItemReorder"
|
|
responses:
|
|
"200":
|
|
description: Reordered
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Item"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/icons/{file}:
|
|
get:
|
|
operationId: getIcon
|
|
summary: Serve an uploaded icon file
|
|
parameters:
|
|
- name: file
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Icon bytes
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/monitors:
|
|
get:
|
|
operationId: listMonitors
|
|
summary: All monitors with live uptime stats
|
|
responses:
|
|
"200":
|
|
description: Monitors ordered by position
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MonitorView"
|
|
post:
|
|
operationId: createMonitor
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MonitorInput"
|
|
responses:
|
|
"201":
|
|
description: Created monitor
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MonitorView"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/monitors/{id}:
|
|
get:
|
|
operationId: getMonitor
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Monitor with stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MonitorView"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
patch:
|
|
operationId: updateMonitor
|
|
summary: Sparse update; `active` toggles pause/resume
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MonitorInput"
|
|
responses:
|
|
"200":
|
|
description: Updated monitor
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MonitorView"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteMonitor
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"204":
|
|
description: Monitor and its heartbeats deleted
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/monitors/{id}/heartbeats:
|
|
get:
|
|
operationId: monitorHeartbeats
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
maximum: 720
|
|
responses:
|
|
"200":
|
|
description: Check history, oldest first
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Heartbeat"
|
|
|
|
/api/monitors/{id}/check:
|
|
post:
|
|
operationId: checkMonitorNow
|
|
summary: Run one check synchronously
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Monitor after the check
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MonitorView"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/push/{token}:
|
|
get:
|
|
operationId: pushMonitorGet
|
|
summary: Record an up heartbeat for a push monitor
|
|
parameters:
|
|
- name: token
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: msg
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: ping
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: Heartbeat recorded
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
post:
|
|
operationId: pushMonitorPost
|
|
summary: Record an up heartbeat for a push monitor
|
|
parameters:
|
|
- name: token
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: msg
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: ping
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: Heartbeat recorded
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/domains:
|
|
get:
|
|
operationId: listDomains
|
|
summary: All tracked domains with expiry countdowns
|
|
responses:
|
|
"200":
|
|
description: Domains ordered by position
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainView"
|
|
post:
|
|
operationId: createDomain
|
|
summary: Track a domain; runs the first WHOIS/DNS/SSL lookup inline
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainInput"
|
|
responses:
|
|
"201":
|
|
description: Domain after the initial lookup
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainView"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
"409":
|
|
description: Domain already tracked
|
|
|
|
/api/domains/{id}:
|
|
get:
|
|
operationId: getDomain
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Domain detail
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainView"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
patch:
|
|
operationId: updateDomain
|
|
summary: Sparse update — settings fields only; lookup data is refreshed separately
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainInput"
|
|
responses:
|
|
"200":
|
|
description: Updated domain
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainView"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteDomain
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"204":
|
|
description: Domain and its check history deleted
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/domains/{id}/refresh:
|
|
post:
|
|
operationId: refreshDomain
|
|
summary: Re-run WHOIS/RDAP + DNS + TLS + geo lookup now
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Domain after the refresh
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainView"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/domains/{id}/checks:
|
|
get:
|
|
operationId: domainChecks
|
|
summary: Snapshot history for change detection
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
maximum: 500
|
|
responses:
|
|
"200":
|
|
description: Snapshots, newest first
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainCheck"
|
|
|
|
/api/widgets/types:
|
|
get:
|
|
operationId: widgetTypes
|
|
summary: Widget registry metadata — drives the add-widget dialog
|
|
responses:
|
|
"200":
|
|
description: Registered widget types
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/WidgetType"
|
|
|
|
/api/widgets/{id}/data:
|
|
get:
|
|
operationId: widgetData
|
|
summary: Live data for one widget item (~30s server-side cache)
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Widget payload; shape depends on config.type
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/WidgetData"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
"502":
|
|
description: Upstream service unreachable
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
|
|
/api/status:
|
|
get:
|
|
operationId: getStatus
|
|
summary: Reachability of each service item's primary URL (~60s server cache)
|
|
responses:
|
|
"200":
|
|
description: Status map keyed by item id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties:
|
|
$ref: "#/components/schemas/Status"
|
|
|
|
/api/domains/{id}/subdomains:
|
|
get:
|
|
operationId: listSubdomains
|
|
summary: Discovered subdomains for a domain
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Subdomain rows, name-sorted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Subdomain"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
/api/domains/{id}/subdomains/refresh:
|
|
post:
|
|
operationId: refreshSubdomains
|
|
summary: Force a crt.sh + DNS discovery run, returns the updated list
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
responses:
|
|
"200":
|
|
description: Subdomain rows after the sweep
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Subdomain"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/notify/test:
|
|
post:
|
|
operationId: notifyTest
|
|
summary: Send a test notification through configured transports
|
|
description: >-
|
|
Fires a test event synchronously through every configured notify_*
|
|
transport, or only the transport named in the body. Returns a
|
|
transport -> "ok" | "error: ..." map.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
transport:
|
|
type: string
|
|
enum: [webhook, slack, discord, telegram, gotify, ntfy, smtp]
|
|
responses:
|
|
"200":
|
|
description: Per-transport delivery results
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/systems:
|
|
get:
|
|
operationId: listSystems
|
|
responses:
|
|
"200":
|
|
description: All monitored systems with their latest sample
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/System"
|
|
post:
|
|
operationId: createSystem
|
|
summary: Register a system; the returned token authenticates agent pushes
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created system
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/System"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/systems/{id}:
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
get:
|
|
operationId: getSystem
|
|
responses:
|
|
"200":
|
|
description: System detail
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/System"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
patch:
|
|
operationId: patchSystem
|
|
summary: Rename or rotate the agent token
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name: { type: string }
|
|
rotateToken: { type: boolean }
|
|
responses:
|
|
"200":
|
|
description: Updated system
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/System"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteSystem
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/systems/{id}/stats:
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
get:
|
|
operationId: systemStats
|
|
summary: Stored agent samples for charting
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema: { type: integer, default: 24, maximum: 168 }
|
|
responses:
|
|
"200":
|
|
description: Samples oldest-to-newest
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
allOf:
|
|
- $ref: "#/components/schemas/StatSample"
|
|
- type: object
|
|
properties:
|
|
ts: { type: string, format: date-time }
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/systems/ingest:
|
|
post:
|
|
operationId: ingestSystem
|
|
summary: "Agent push endpoint; Authorization: Bearer <system token>"
|
|
security:
|
|
- bearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/StatSample"
|
|
responses:
|
|
"200":
|
|
description: Sample stored
|
|
"401":
|
|
description: Missing or unknown token
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/incidents:
|
|
get:
|
|
operationId: listIncidents
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
description: "`open` filters to open+ack"
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Incidents newest-first, updates embedded
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Incident"
|
|
post:
|
|
operationId: createIncident
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/IncidentInput"
|
|
responses:
|
|
"201":
|
|
description: Created incident
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Incident"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/incidents/{id}:
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
patch:
|
|
operationId: patchIncident
|
|
summary: Update fields; a status change appends a timeline entry
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/IncidentInput"
|
|
responses:
|
|
"200":
|
|
description: Updated incident
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Incident"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteIncident
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/incidents/{id}/updates:
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
post:
|
|
operationId: addIncidentUpdate
|
|
summary: Append a timeline note; `status` also moves the incident
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/IncidentInput"
|
|
responses:
|
|
"200":
|
|
description: Incident with updated timeline
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Incident"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/maintenance:
|
|
get:
|
|
operationId: listWindows
|
|
responses:
|
|
"200":
|
|
description: Maintenance windows newest-first
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MaintenanceWindow"
|
|
post:
|
|
operationId: createWindow
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MaintenanceWindowInput"
|
|
responses:
|
|
"201":
|
|
description: Created window
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MaintenanceWindow"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/maintenance/{id}:
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
delete:
|
|
operationId: deleteWindow
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/status-pages:
|
|
get:
|
|
operationId: listStatusPages
|
|
responses:
|
|
"200":
|
|
description: All status pages
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/StatusPage"
|
|
post:
|
|
operationId: createStatusPage
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/StatusPageInput"
|
|
responses:
|
|
"201":
|
|
description: Created page
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/StatusPage"
|
|
"409":
|
|
description: Slug already in use
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/status-pages/{id}:
|
|
parameters:
|
|
- $ref: "#/components/parameters/id"
|
|
patch:
|
|
operationId: patchStatusPage
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/StatusPageInput"
|
|
responses:
|
|
"200":
|
|
description: Updated page
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/StatusPage"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
delete:
|
|
operationId: deleteStatusPage
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/status-pages/{slug}/public:
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
get:
|
|
operationId: publicStatus
|
|
summary: Live public view for a status page
|
|
responses:
|
|
"200":
|
|
description: Title, overall state, monitors, systems, incidents, maintenance
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PublicStatus"
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/badge/{kind}/{file}:
|
|
parameters:
|
|
- name: kind
|
|
in: path
|
|
required: true
|
|
schema: { type: string, enum: [monitor, domain, system] }
|
|
- name: file
|
|
in: path
|
|
required: true
|
|
description: "Entity id, conventionally suffixed .svg"
|
|
schema: { type: string }
|
|
get:
|
|
operationId: badge
|
|
summary: Stateless SVG shield from live state
|
|
responses:
|
|
"200":
|
|
description: SVG badge
|
|
content:
|
|
image/svg+xml: {}
|
|
"404":
|
|
$ref: "#/components/responses/NotFound"
|
|
|
|
/api/metrics:
|
|
get:
|
|
operationId: metrics
|
|
summary: Prometheus text exposition
|
|
responses:
|
|
"200":
|
|
description: text/plain metrics
|
|
content:
|
|
text/plain: {}
|
|
|
|
/api/import/csv:
|
|
post:
|
|
operationId: importCSV
|
|
summary: "Bulk import from CSV; ?kind=monitors|domains"
|
|
parameters:
|
|
- name: kind
|
|
in: query
|
|
schema: { type: string, enum: [monitors, domains], default: monitors }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
text/csv:
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Import summary
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
created: { type: integer }
|
|
skipped: { type: integer }
|
|
errors:
|
|
type: array
|
|
items: { type: string }
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/settings:
|
|
get:
|
|
operationId: getSettings
|
|
responses:
|
|
"200":
|
|
description: All settings as key/value map
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: true
|
|
put:
|
|
operationId: putSettings
|
|
summary: Merge settings (keys not sent are preserved)
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: true
|
|
responses:
|
|
"200":
|
|
description: Full settings map after merge
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: true
|
|
|
|
/api/export:
|
|
get:
|
|
operationId: exportBoard
|
|
summary: Full JSON backup (sections, items, urls, settings)
|
|
responses:
|
|
"200":
|
|
description: Board export
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Export"
|
|
|
|
/api/import:
|
|
post:
|
|
operationId: importBoard
|
|
summary: Replace board state from an export payload
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Export"
|
|
responses:
|
|
"200":
|
|
description: Imported board tree
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Section"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/import/external:
|
|
post:
|
|
operationId: importExternal
|
|
summary: >
|
|
Import a foreign dashboard config — Homepage services.yml, Homarr
|
|
JSON export, or Dashy conf.yml. Format is auto-detected; the board
|
|
is replaced and existing settings are preserved.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/octet-stream:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
application/json:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
text/yaml:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
responses:
|
|
"200":
|
|
description: Imported board tree
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Section"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
|
|
/api/auth/session:
|
|
get:
|
|
operationId: authSession
|
|
summary: Auth state — enabled flag, whether setup is needed, and current session
|
|
responses:
|
|
"200":
|
|
description: Session state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AuthSession"
|
|
|
|
/api/auth/setup:
|
|
post:
|
|
operationId: authSetup
|
|
summary: Create the first local admin — only while no users exist
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [username, password]
|
|
properties:
|
|
username:
|
|
type: string
|
|
password:
|
|
type: string
|
|
minLength: 8
|
|
responses:
|
|
"201":
|
|
description: Admin created; session cookie set
|
|
"400":
|
|
$ref: "#/components/responses/BadRequest"
|
|
"409":
|
|
description: Setup already completed
|
|
|
|
/api/auth/login:
|
|
post:
|
|
operationId: authLogin
|
|
summary: Password login — sets a session cookie; rate-limited per IP
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [username, password]
|
|
properties:
|
|
username:
|
|
type: string
|
|
password:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Signed in
|
|
"401":
|
|
description: Invalid credentials
|
|
"429":
|
|
description: Too many attempts
|
|
|
|
/api/auth/logout:
|
|
post:
|
|
operationId: authLogout
|
|
summary: Destroy the current session
|
|
responses:
|
|
"204":
|
|
description: Signed out
|
|
|
|
/api/auth/disable:
|
|
post:
|
|
operationId: authDisable
|
|
summary: Turn authentication off — requires an active session
|
|
responses:
|
|
"204":
|
|
description: Disabled
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
parameters:
|
|
id:
|
|
name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
|
|
responses:
|
|
NotFound:
|
|
description: Not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
BadRequest:
|
|
description: Invalid input
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
|
|
schemas:
|
|
Health:
|
|
type: object
|
|
required: [status]
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: ok
|
|
AuthSession:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
setup:
|
|
type: boolean
|
|
description: True when auth is on but no user exists yet
|
|
authed:
|
|
type: boolean
|
|
username:
|
|
type: string
|
|
|
|
Error:
|
|
type: object
|
|
required: [error]
|
|
properties:
|
|
error:
|
|
type: string
|
|
Url:
|
|
type: object
|
|
required: [id, url, label]
|
|
properties:
|
|
id:
|
|
type: string
|
|
url:
|
|
type: string
|
|
format: uri
|
|
label:
|
|
type: string
|
|
description: Tag such as "local" / "external" or a custom label
|
|
position:
|
|
type: number
|
|
UrlInput:
|
|
type: object
|
|
required: [url]
|
|
properties:
|
|
url:
|
|
type: string
|
|
format: uri
|
|
label:
|
|
type: string
|
|
default: ""
|
|
Item:
|
|
type: object
|
|
required: [id, sectionId, kind, name, position, urls]
|
|
properties:
|
|
id:
|
|
type: string
|
|
sectionId:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
enum: [service, widget]
|
|
name:
|
|
type: string
|
|
icon:
|
|
type: string
|
|
description: "/api/icons/<file> path or remote URL; empty = letter tile"
|
|
position:
|
|
type: number
|
|
config:
|
|
type: object
|
|
nullable: true
|
|
additionalProperties: true
|
|
description: Widget config (Phase 2); null for services
|
|
urls:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Url"
|
|
ItemInput:
|
|
type: object
|
|
required: [sectionId, name]
|
|
properties:
|
|
sectionId:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
enum: [service, widget]
|
|
default: service
|
|
name:
|
|
type: string
|
|
icon:
|
|
type: string
|
|
config:
|
|
type: object
|
|
nullable: true
|
|
additionalProperties: true
|
|
description: Widget config — keys defined by the widget type's fields
|
|
urls:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/UrlInput"
|
|
ItemPatch:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
icon:
|
|
type: string
|
|
config:
|
|
type: object
|
|
nullable: true
|
|
additionalProperties: true
|
|
urls:
|
|
type: array
|
|
description: Full replacement of the item's URL list
|
|
items:
|
|
$ref: "#/components/schemas/UrlInput"
|
|
Section:
|
|
type: object
|
|
required: [id, name, position, collapsed, boardId, items]
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
position:
|
|
type: number
|
|
collapsed:
|
|
type: boolean
|
|
boardId:
|
|
type: string
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Item"
|
|
Board:
|
|
type: object
|
|
required: [id, slug, name, position]
|
|
properties:
|
|
id:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
name:
|
|
type: string
|
|
position:
|
|
type: number
|
|
SectionInput:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
boardId:
|
|
type: string
|
|
SectionPatch:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
collapsed:
|
|
type: boolean
|
|
Reorder:
|
|
type: object
|
|
required: [id]
|
|
properties:
|
|
id:
|
|
type: string
|
|
beforeId:
|
|
type: string
|
|
description: Neighbor now before the moved entity; null if first
|
|
afterId:
|
|
type: string
|
|
description: Neighbor now after the moved entity; null if last
|
|
ItemReorder:
|
|
allOf:
|
|
- $ref: "#/components/schemas/Reorder"
|
|
- type: object
|
|
properties:
|
|
sectionId:
|
|
type: string
|
|
description: Target section (defaults to current)
|
|
Status:
|
|
type: object
|
|
required: [status]
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum: [up, down]
|
|
latencyMs:
|
|
type: integer
|
|
checkedAt:
|
|
type: string
|
|
format: date-time
|
|
Monitor:
|
|
type: object
|
|
required: [id, name, type, active, status]
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: [http, tcp, ping, dns, keyword, json, push]
|
|
url:
|
|
type: string
|
|
hostname:
|
|
type: string
|
|
port:
|
|
type: integer
|
|
method:
|
|
type: string
|
|
headers:
|
|
type: string
|
|
description: JSON object of request headers
|
|
body:
|
|
type: string
|
|
keyword:
|
|
type: string
|
|
keywordInvert:
|
|
type: boolean
|
|
jsonQuery:
|
|
type: string
|
|
description: Dot path into a JSON response, e.g. "data.status"
|
|
expected:
|
|
type: string
|
|
dnsType:
|
|
type: string
|
|
intervalS:
|
|
type: integer
|
|
timeoutS:
|
|
type: integer
|
|
retries:
|
|
type: integer
|
|
active:
|
|
type: boolean
|
|
status:
|
|
type: string
|
|
enum: [up, down, pending, paused, maintenance]
|
|
pushToken:
|
|
type: string
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
notes:
|
|
type: string
|
|
alerts:
|
|
$ref: "#/components/schemas/AlertRules"
|
|
position:
|
|
type: number
|
|
lastCheck:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
AlertRules:
|
|
type: object
|
|
description: Per-target alert rules; omitted fields keep defaults.
|
|
properties:
|
|
consecutiveFailures:
|
|
type: integer
|
|
description: Checks must fail N times in a row before status flips down
|
|
latencyWarnMs:
|
|
type: integer
|
|
description: Notify once when an up check's ping crosses this threshold
|
|
certDays:
|
|
type: integer
|
|
description: Domain TLS expiry threshold; overrides alertDaysBefore
|
|
mute:
|
|
type: boolean
|
|
description: Suppress notifications; incidents/status still record
|
|
MonitorInput:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: [http, tcp, ping, dns, keyword, json, push]
|
|
url:
|
|
type: string
|
|
hostname:
|
|
type: string
|
|
port:
|
|
type: integer
|
|
method:
|
|
type: string
|
|
headers:
|
|
type: string
|
|
body:
|
|
type: string
|
|
keyword:
|
|
type: string
|
|
keywordInvert:
|
|
type: boolean
|
|
jsonQuery:
|
|
type: string
|
|
expected:
|
|
type: string
|
|
dnsType:
|
|
type: string
|
|
intervalS:
|
|
type: integer
|
|
timeoutS:
|
|
type: integer
|
|
retries:
|
|
type: integer
|
|
active:
|
|
type: boolean
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
notes:
|
|
type: string
|
|
alerts:
|
|
$ref: "#/components/schemas/AlertRules"
|
|
UptimeStats:
|
|
type: object
|
|
properties:
|
|
up:
|
|
type: integer
|
|
down:
|
|
type: integer
|
|
uptime24h:
|
|
type: number
|
|
uptime30d:
|
|
type: number
|
|
avgPing24h:
|
|
type: integer
|
|
MonitorView:
|
|
allOf:
|
|
- $ref: "#/components/schemas/Monitor"
|
|
- type: object
|
|
properties:
|
|
stats:
|
|
$ref: "#/components/schemas/UptimeStats"
|
|
Heartbeat:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
status:
|
|
type: string
|
|
enum: [up, down]
|
|
pingMs:
|
|
type: integer
|
|
msg:
|
|
type: string
|
|
certExpiry:
|
|
type: integer
|
|
checkedAt:
|
|
type: string
|
|
format: date-time
|
|
Domain:
|
|
type: object
|
|
required: [id, name, active]
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
tld:
|
|
type: string
|
|
active:
|
|
type: boolean
|
|
autoRenew:
|
|
type: boolean
|
|
alertDaysBefore:
|
|
type: integer
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
notes:
|
|
type: string
|
|
expiryDate:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
creationDate:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
updatedDate:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
registrarName:
|
|
type: string
|
|
registrarId:
|
|
type: string
|
|
registrarUrl:
|
|
type: string
|
|
registryDomainId:
|
|
type: string
|
|
dnssec:
|
|
type: string
|
|
statuses:
|
|
type: array
|
|
items:
|
|
type: string
|
|
privacyEnabled:
|
|
type: boolean
|
|
transferLock:
|
|
type: boolean
|
|
registrantName:
|
|
type: string
|
|
registrantOrg:
|
|
type: string
|
|
registrantCountry:
|
|
type: string
|
|
abuseEmail:
|
|
type: string
|
|
nameServers:
|
|
type: array
|
|
items:
|
|
type: string
|
|
mxRecords:
|
|
type: array
|
|
items:
|
|
type: string
|
|
txtRecords:
|
|
type: array
|
|
items:
|
|
type: string
|
|
cname:
|
|
type: string
|
|
ipv4:
|
|
type: array
|
|
items:
|
|
type: string
|
|
ipv6:
|
|
type: array
|
|
items:
|
|
type: string
|
|
sslIssuer:
|
|
type: string
|
|
sslValidFrom:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
sslValidTo:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
sslSubject:
|
|
type: string
|
|
sslFingerprint:
|
|
type: string
|
|
sslKeySize:
|
|
type: integer
|
|
sslSigAlgo:
|
|
type: string
|
|
sslAltNames:
|
|
type: array
|
|
items:
|
|
type: string
|
|
hostCountry:
|
|
type: string
|
|
hostCountryCode:
|
|
type: string
|
|
hostRegion:
|
|
type: string
|
|
hostCity:
|
|
type: string
|
|
hostIsp:
|
|
type: string
|
|
hostOrg:
|
|
type: string
|
|
hostAs:
|
|
type: string
|
|
hostLat:
|
|
type: number
|
|
hostLon:
|
|
type: number
|
|
dnsProvider:
|
|
type: string
|
|
emailProvider:
|
|
type: string
|
|
hostingProvider:
|
|
type: string
|
|
caProvider:
|
|
type: string
|
|
records:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DNSRecord"
|
|
providers:
|
|
$ref: "#/components/schemas/Providers"
|
|
headers:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
faviconUrl:
|
|
type: string
|
|
lookupError:
|
|
type: string
|
|
intervalH:
|
|
type: integer
|
|
lastChecked:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
alerts:
|
|
$ref: "#/components/schemas/AlertRules"
|
|
position:
|
|
type: number
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
DomainInput:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
active:
|
|
type: boolean
|
|
autoRenew:
|
|
type: boolean
|
|
alertDaysBefore:
|
|
type: integer
|
|
intervalH:
|
|
type: integer
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
notes:
|
|
type: string
|
|
alerts:
|
|
$ref: "#/components/schemas/AlertRules"
|
|
Provider:
|
|
type: object
|
|
description: Detected vendor behind a record or role
|
|
properties:
|
|
name:
|
|
type: string
|
|
domain:
|
|
type: string
|
|
description: brand domain the favicon icon was derived from
|
|
icon:
|
|
type: string
|
|
Providers:
|
|
type: object
|
|
description: Detected vendor strip — registrar, DNS, hosting, email, CA
|
|
properties:
|
|
registrar:
|
|
$ref: "#/components/schemas/Provider"
|
|
nullable: true
|
|
dns:
|
|
$ref: "#/components/schemas/Provider"
|
|
nullable: true
|
|
email:
|
|
$ref: "#/components/schemas/Provider"
|
|
nullable: true
|
|
hosting:
|
|
$ref: "#/components/schemas/Provider"
|
|
nullable: true
|
|
ca:
|
|
$ref: "#/components/schemas/Provider"
|
|
nullable: true
|
|
DNSRecord:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [A, AAAA, CNAME, NS, MX, TXT]
|
|
value:
|
|
type: string
|
|
priority:
|
|
type: integer
|
|
nullable: true
|
|
description: MX preference
|
|
provider:
|
|
$ref: "#/components/schemas/Provider"
|
|
nullable: true
|
|
DomainView:
|
|
allOf:
|
|
- $ref: "#/components/schemas/Domain"
|
|
- type: object
|
|
properties:
|
|
daysUntilExpiry:
|
|
type: integer
|
|
nullable: true
|
|
sslDaysUntilExpiry:
|
|
type: integer
|
|
nullable: true
|
|
expiring:
|
|
type: boolean
|
|
sslExpiring:
|
|
type: boolean
|
|
Subdomain:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
ips:
|
|
type: array
|
|
items:
|
|
type: string
|
|
firstSeen:
|
|
type: string
|
|
format: date-time
|
|
lastSeen:
|
|
type: string
|
|
format: date-time
|
|
DomainCheck:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
expiryDate:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
sslValidTo:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
ipv4:
|
|
type: array
|
|
items:
|
|
type: string
|
|
nameServers:
|
|
type: array
|
|
items:
|
|
type: string
|
|
checkedAt:
|
|
type: string
|
|
format: date-time
|
|
StatSample:
|
|
type: object
|
|
description: One agent push; missing fields mean the platform can't provide them
|
|
properties:
|
|
host: { type: string }
|
|
os: { type: string }
|
|
arch: { type: string }
|
|
cpuModel: { type: string }
|
|
cores: { type: integer }
|
|
intervalS: { type: integer }
|
|
uptimeS: { type: number }
|
|
cpu:
|
|
type: number
|
|
description: CPU usage percent 0-100
|
|
memTotal: { type: number, description: bytes }
|
|
memUsed: { type: number, description: bytes }
|
|
swapTotal: { type: number, description: bytes }
|
|
swapUsed: { type: number, description: bytes }
|
|
diskTotal: { type: number, description: root filesystem bytes }
|
|
diskUsed: { type: number, description: bytes }
|
|
netRx: { type: number, description: bytes per second }
|
|
netTx: { type: number, description: bytes per second }
|
|
load1: { type: number }
|
|
load5: { type: number }
|
|
load15: { type: number }
|
|
temps:
|
|
type: object
|
|
additionalProperties: { type: number }
|
|
description: Sensor label -> celsius
|
|
containers:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ContainerStat"
|
|
smart:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SmartDisk"
|
|
zfs:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ZFSPool"
|
|
gpu:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/GPUStat"
|
|
ContainerStat:
|
|
type: object
|
|
properties:
|
|
name: { type: string }
|
|
state: { type: string }
|
|
cpu: { type: number, description: "percent of one core, may exceed 100" }
|
|
memUsed: { type: number, description: bytes }
|
|
memLimit: { type: number, description: bytes }
|
|
SmartDisk:
|
|
type: object
|
|
properties:
|
|
device: { type: string }
|
|
model: { type: string }
|
|
passed: { type: boolean, nullable: true }
|
|
tempC: { type: number }
|
|
ZFSPool:
|
|
type: object
|
|
properties:
|
|
name: { type: string }
|
|
health: { type: string }
|
|
size: { type: number, description: bytes }
|
|
free: { type: number, description: bytes }
|
|
GPUStat:
|
|
type: object
|
|
properties:
|
|
name: { type: string }
|
|
tempC: { type: number }
|
|
utilPct: { type: number }
|
|
memUsed: { type: number, description: bytes }
|
|
memTotal: { type: number, description: bytes }
|
|
System:
|
|
type: object
|
|
required: [id, name, token, status]
|
|
properties:
|
|
id: { type: string }
|
|
name: { type: string }
|
|
token:
|
|
type: string
|
|
description: Agent bearer token
|
|
host: { type: string }
|
|
os: { type: string }
|
|
arch: { type: string }
|
|
cpuModel: { type: string }
|
|
cores: { type: integer }
|
|
intervalS: { type: integer }
|
|
status:
|
|
type: string
|
|
enum: [pending, up, down]
|
|
lastSeenAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
latest:
|
|
$ref: "#/components/schemas/StatSample"
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
IncidentUpdate:
|
|
type: object
|
|
properties:
|
|
id: { type: integer }
|
|
status: { type: string }
|
|
message: { type: string }
|
|
at: { type: string, format: date-time }
|
|
Incident:
|
|
type: object
|
|
required: [id, title, severity, status]
|
|
properties:
|
|
id: { type: string }
|
|
title: { type: string }
|
|
severity: { type: string, enum: [minor, major, critical] }
|
|
status: { type: string, enum: [open, ack, resolved, closed] }
|
|
monitorId: { type: string, nullable: true }
|
|
updates:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/IncidentUpdate"
|
|
createdAt: { type: string, format: date-time }
|
|
updatedAt: { type: string, format: date-time }
|
|
IncidentInput:
|
|
type: object
|
|
properties:
|
|
title: { type: string }
|
|
severity: { type: string, enum: [minor, major, critical] }
|
|
status: { type: string, enum: [open, ack, resolved, closed] }
|
|
monitorId: { type: string }
|
|
message:
|
|
type: string
|
|
description: Timeline note attached to the create/transition
|
|
MaintenanceWindow:
|
|
type: object
|
|
required: [id, title, startsAt, endsAt]
|
|
properties:
|
|
id: { type: string }
|
|
title: { type: string }
|
|
startsAt: { type: string, format: date-time }
|
|
endsAt: { type: string, format: date-time }
|
|
monitorIds:
|
|
type: array
|
|
items: { type: string }
|
|
description: Empty array covers all monitors
|
|
active: { type: boolean }
|
|
createdAt: { type: string, format: date-time }
|
|
MaintenanceWindowInput:
|
|
type: object
|
|
required: [title, startsAt, endsAt]
|
|
properties:
|
|
title: { type: string }
|
|
startsAt: { type: string, format: date-time }
|
|
endsAt: { type: string, format: date-time }
|
|
monitorIds:
|
|
type: array
|
|
items: { type: string }
|
|
StatusPage:
|
|
type: object
|
|
required: [id, slug, title]
|
|
properties:
|
|
id: { type: string }
|
|
slug: { type: string }
|
|
title: { type: string }
|
|
description: { type: string }
|
|
monitorIds:
|
|
type: array
|
|
items: { type: string }
|
|
description: Empty array means all active monitors
|
|
systemIds:
|
|
type: array
|
|
items: { type: string }
|
|
createdAt: { type: string, format: date-time }
|
|
StatusPageInput:
|
|
type: object
|
|
required: [title]
|
|
properties:
|
|
slug: { type: string }
|
|
title: { type: string }
|
|
description: { type: string }
|
|
monitorIds:
|
|
type: array
|
|
items: { type: string }
|
|
systemIds:
|
|
type: array
|
|
items: { type: string }
|
|
PublicStatus:
|
|
type: object
|
|
properties:
|
|
title: { type: string }
|
|
slug: { type: string }
|
|
description: { type: string }
|
|
overall: { type: string, enum: [up, down, maintenance, pending] }
|
|
monitors:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
name: { type: string }
|
|
status: { type: string }
|
|
uptime24h: { type: number }
|
|
systems:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
name: { type: string }
|
|
status: { type: string }
|
|
incidents:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Incident"
|
|
maintenance:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MaintenanceWindow"
|
|
WidgetField:
|
|
type: object
|
|
required: [key, label]
|
|
properties:
|
|
key:
|
|
type: string
|
|
label:
|
|
type: string
|
|
secret:
|
|
type: boolean
|
|
description: Render as password input; never logged
|
|
placeholder:
|
|
type: string
|
|
required:
|
|
type: boolean
|
|
WidgetType:
|
|
type: object
|
|
required: [type, name, fields]
|
|
properties:
|
|
type:
|
|
type: string
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
local:
|
|
type: boolean
|
|
description: Client-rendered (e.g. clock); no /data fetch needed
|
|
fields:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/WidgetField"
|
|
WidgetData:
|
|
type: object
|
|
required: [data]
|
|
properties:
|
|
data:
|
|
type: object
|
|
additionalProperties: true
|
|
fetchedAt:
|
|
type: string
|
|
format: date-time
|
|
Export:
|
|
type: object
|
|
required: [version, sections]
|
|
properties:
|
|
version:
|
|
type: integer
|
|
settings:
|
|
type: object
|
|
additionalProperties: true
|
|
sections:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Section"
|
|
boards:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Board"
|