Shumoku

API Reference

HTTP endpoints and WebSocket protocol

Authentication

All API endpoints except the health check, token-scoped shared views, and secret-authenticated webhook ingress require administrator authentication. Browsers use the session cookie obtained by logging in:

POST /api/auth/login
Content-Type: application/json

{ "password": "your-password" }

Development automation

When the Server is started from the repository with bun run dev:server, the launcher binds the API to loopback and creates an ephemeral 256-bit development credential. Agents and local scripts should use the request wrapper; they do not need to handle or print the credential:

bun run dev:server:request -- GET /api/topologies
bun run dev:server:request -- POST /api/topologies/example/rebuild
bun run dev:server:request -- PATCH /api/topologies/example/discovery-policy \
  --json '{"scope":"topology","attachments":[]}'

The wrapper uses the standard Authorization: Bearer scheme. This path is available only when NODE_ENV=development, requires the API to be bound to 127.0.0.1 or ::1, accepts only normalized /api/* paths, and refuses to send the generated credential to any remote HTTP or HTTPS origin. Production continues to accept session authentication only. The credential is stored in a gitignored owner-only file while the API is running and is removed on shutdown.

Starting apps/server/api directly with bun run dev does not create this credential; use the server-level command above when automating API access.

Machine-readable contract

GET /api/openapi.json returns the OpenAPI 3.1 contract. It requires the same administrator session or development Bearer credential as management endpoints:

bun run dev:server:request -- GET /api/openapi.json

Request and response schemas are the source of truth for every HTTP route, and request schemas also perform runtime validation. The document covers management, sharing, discovery, rendering, mapping, sync, plugins, and webhook ingress.

For repository development, bun run openapi:generate writes the deterministic apps/server/api/openapi.json snapshot and the web client's generated TypeScript definitions. The web client consumes those definitions with openapi-fetch; raw fetch is reserved for multipart upload and the tagged-Map view payload. Every operation has a deterministic, unique operationId derived from its HTTP method and path, so generated SDK names remain stable while the route remains stable. CI checks artifact drift, requires every runtime HTTP route to exist in OpenAPI, and runs oasdiff against the PR base branch. Definite and potential breaking changes fail the compatibility check and must be redesigned or handled as an intentional versioned change.

Error responses

JSON error responses use one envelope across validation, authentication, and feature routes:

{
  "code": "NOT_FOUND",
  "message": "Topology not found",
  "requestId": "00000000-0000-4000-8000-000000000000",
  "error": "Topology not found"
}

Clients should branch on code, display message, and include requestId when reporting a failure. error is a deprecated alias of message retained for compatibility with older clients.

Shared views (public, token-scoped)

The only endpoints reachable without a session are the share routes below (plus /api/health). A share token grants read-only access to a single topology — or, for a dashboard, to just the topology/data-source ids that dashboard's widgets reference. Responses are projected to a public shape: internal fields (the resource's own share token, data-source ids, host mappings, port aliases, timestamps) are never returned.

MethodEndpointDescription
GET/api/share/topologies/:tokenShared topology context (nodes/edges/metrics)
GET/api/share/topologies/:token/graphShared topology as a NetworkGraph
GET/api/share/topologies/:token/renderShared topology render output
GET/api/share/dashboards/:tokenShared dashboard shell (layout)
GET/api/share/dashboards/:token/topologies/:idTopology metadata for a widget in this dashboard
GET/api/share/dashboards/:token/topologies/:id/graphNetworkGraph for a widget in this dashboard
GET/api/share/dashboards/:token/topologies/:id/contextContext for a device-status widget
GET/api/share/dashboards/:token/datasources/:id/alertsAlerts for an alert widget

A dashboard-scoped request whose :id is not referenced by the dashboard's layout returns 404, so the token cannot enumerate unrelated resources. The management endpoints below (/api/topologies/:id, /api/dashboards/:id, /api/datasources/:id/alerts, …) always require authentication.

HTTP Endpoints

Data Sources

MethodEndpointDescription
GET/api/datasourcesList all data sources
POST/api/datasourcesCreate data source
GET/api/datasources/:idGet data source details
PUT/api/datasources/:idUpdate data source
DELETE/api/datasources/:idDelete data source
GET/api/datasources/typesList plugin types and form schemas
GET/api/datasources/by-capability/:capabilityList sources by capability
GET/api/datasources/:id/config-options/:keyGet dynamic form options
GET/api/datasources/:id/connection-infoGet display-only connection information
GET/api/datasources/:id/topologiesList attached topologies
POST/api/datasources/:id/testTest connection
GET/api/datasources/:id/hostsList monitored hosts
GET/api/datasources/:id/hosts/:hostId/itemsHost metrics items
GET/api/datasources/:id/alertsGet alerts

Topologies

MethodEndpointDescription
GET/api/topologiesList all topologies
POST/api/topologiesCreate topology
GET/api/topologies/:idGet topology details
PUT/api/topologies/:idUpdate topology
DELETE/api/topologies/:idDelete topology
GET/api/topologies/:id/renderGet rendered layout data
GET/api/topologies/:id/sourcesList linked data sources
POST/api/topologies/:id/sourcesLink a data source

Dashboards

MethodEndpointDescription
GET/api/dashboardsList all dashboards
POST/api/dashboardsCreate dashboard
GET/api/dashboards/:idGet dashboard details
PUT/api/dashboards/:idUpdate dashboard
DELETE/api/dashboards/:idDelete dashboard

Plugins

MethodEndpointDescription
GET/api/pluginsList all plugins
POST/api/pluginsAdd plugin (URL/path/upload)
DELETE/api/plugins/:idRemove plugin

Webhooks

Webhook endpoints do not use session authentication. Each request must instead carry the webhook secret configured on the source, supplied via the X-Webhook-Secret header (preferred) or a ?secret= query parameter. The secret is compared in constant time; a missing secret returns 401, an unknown target returns 404, and a wrong secret returns 401.

The general form is POST /api/webhooks/:type/:id, where :id is the id of the source (shown in its settings, not the secret itself). type=topology re-fetches a webhook-mode topology source's graph; any other type is dispatched to the matching data-source plugin — currently only grafana handles webhooks.

MethodEndpointDescription
POST/api/webhooks/topology/:idTopology source webhook (:id = topology source id) — re-syncs the source, e.g. from NetBox
POST/api/webhooks/grafana/:idGrafana alert webhook (:id = data source id)
GET/api/webhooks/healthWebhook health check

Other

MethodEndpointDescription
GET/api/healthHealth check (no auth required)
GET/api/systemBuild and update information
GET/api/admin/statusRedacted runtime, scheduler, plugin, and subscriber status
GET/api/openapi.jsonAuthoritative OpenAPI 3.1 contract
GET/api/auth/statusCheck authentication state
POST/api/auth/setupInitial password setup
POST/api/auth/logoutLogout

WebSocket

Connect to ws://<host>/ws for real-time metrics streaming.

Client Messages

// Subscribe to topology updates
{ "type": "subscribe", "topology": "<topology-id>" }

// Filter specific nodes/links
{ "type": "filter", "nodes": ["router1"], "links": ["link-0"] }

Server Messages

{
  "type": "metrics",
  "data": {
    "nodes": {
      "router1": { "status": "up" }
    },
    "links": {
      "link-0": {
        "status": "up",
        "utilization": { "in": 45.2, "out": 12.8 }
      }
    },
    "timestamp": 1705849200000
  }
}

On this page