Pulse provides a comprehensive REST API for automation and integration.
Base URL: http://<your-pulse-ip>:7655/api
Most API requests require authentication via one of the following methods:
Pass the token in the X-API-Token header.
curl -H "X-API-Token: your-token" http://localhost:7655/api/healthcurl -H "Authorization: Bearer your-token" http://localhost:7655/api/healthStandard browser session cookie (used by the UI).
Session endpoints:
POST /api/login(setspulse_session+pulse_csrf)POST /api/logout(clears session)
Login body:
{ "username": "admin", "password": "secret", "rememberMe": true }Public endpoints include:
GET /api/healthGET /api/versionGET /api/agent/version(agent update checks)GET /api/setup-script(requires a setup token)
Some endpoints require admin privileges and/or scopes. Common scopes include:
monitoring:readsettings:readsettings:writeagent:config:readagent:manage
Endpoints that require admin access are noted below.
GET /api/health
Check if Pulse is running.
{
"status": "healthy",
"timestamp": 1700000000,
"uptime": 3600,
"devModeSSH": false
}GET /api/state
Returns the complete state of your infrastructure (Nodes, VMs, Containers, Storage, Alerts). This is the main endpoint used by the dashboard.
GET /api/state/summary
Returns a lightweight integration summary for external dashboards and checks. Requires monitoring:read.
{
"activeAlerts": 1,
"nodes": 2,
"vms": 8,
"containers": 12,
"dockerHosts": [
{
"name": "Docker Host",
"containers": 5,
"uptimeSeconds": 86400,
"cpuUsagePercent": 12.5
}
],
"lastUpdate": "2026-05-24T10:11:12Z"
}GET /simple-stats
Lightweight HTML status page for quick checks.
GET /api/resources
Returns the unified resource list with pagination + aggregations. Requires monitoring:read.
Query params:
type: comma-separated list (e.g.,agent,vm,system-container,container,docker-service,storage,pbs,pmg,k8s-cluster,k8s-node,pod,k8s-deployment,physical_disk,ceph)source: comma-separated list (e.g.,proxmox,agent,docker,pbs,pmg,kubernetes)status: comma-separated list (online,offline,warning,unknown)parent: parent resource IDcluster: cluster namenamespace: Kubernetes namespace (filters Kubernetes resources only)q: name search (contains match)tags: comma-separated tagspage: page number (default1)limit: page size (default50, max100)sort:name(default),status,type,lastSeenorder:asc(default) ordesc
Note: GET /api/resources is optimized for list views. Some large, platform-specific fields may be omitted from the list response and are only returned by GET /api/resources/{id}.
Note: guest disk usage percentages use -1 as an "unknown" sentinel — reported when a VM is stopped or its guest agent is unavailable, so there is no filesystem view to measure. Consumers should treat negative values as "no data", not as a percentage; the accompanying diskStatusReason field (e.g. vm-stopped, agent-disabled) says why.
Availability is an additive resource facet. availability is the compatibility
summary used by existing clients; availabilityChecks contains every check
attached to the resource. Each check can include correlationState
(attached, standalone, ambiguous, or unresolved), its correlation
rule/reason/candidate count, and an evidence envelope with observation and
validity timestamps. Attached targets also add a checks relationship and do
not appear as separate network-endpoint rows.
GET /api/resources/stats
Returns aggregations (counts + health rollups).
GET /api/resources/k8s/namespaces?cluster=<clusterName>
Returns namespace-level rollups (pods + deployments) for a Kubernetes cluster. Requires monitoring:read.
{
"cluster": "prod-k8s",
"data": [
{
"namespace": "default",
"pods": { "total": 12, "online": 10, "warning": 2, "offline": 0, "unknown": 0 },
"deployments": { "total": 3, "online": 3, "warning": 0, "offline": 0, "unknown": 0 }
}
]
}GET /api/resources/{id}
Fetch a single resource by ID.
GET /api/resources/{id}/children
Returns child resources for the parent ID.
GET /api/resources/{id}/metrics
Returns the resource metrics payload.
POST /api/resources/{id}/link
Manually link two resources.
{ "targetId": "resource-id", "reason": "optional note" }POST /api/resources/{id}/unlink
Manually unlink two resources.
{ "targetId": "resource-id", "reason": "optional note" }POST /api/resources/{id}/report-merge
Report an incorrect merge (creates exclusions).
{ "sources": ["proxmox", "agent"], "notes": "optional note" }GET /api/connections
Returns the canonical fleet connections ledger with per-row fleet-governance state. Requires admin access with settings:read.
The payload is the source of truth for enrollment, liveness, version drift, adapter health, config rollout, credential posture, update posture, and remote-control posture. Consumers must not rebuild those states from provider-specific config stores or display labels.
CLI adapter:
PULSE_API_TOKEN=your-token pulse fleet connections \
--api-url http://localhost:7655POST /api/actions/plan
Returns the deterministic pre-execution plan for a capability advertised on a unified resource. Requires ai:execute.
This endpoint is API-first and plan-only: it resolves the resource from the unified registry, verifies the requested capability and parameter schema, returns approval policy, blast radius, stale-plan hashes, and preflight checks, and does not approve or execute anything.
POST /api/actions/{id}/decision
Records an explicit approved or rejected decision for a persisted pending_approval action. It does not execute the action.
POST /api/actions/{id}/execute
Starts execution only for an approved action or an approval-free executable plan, records executing before dispatch, and records the terminal result afterward. Dry-run-only plans are rejected and cannot be executed through this endpoint.
CLI adapter:
PULSE_API_TOKEN=your-token pulse actions capabilities \
--api-url http://localhost:7655 \
--resource-id vm:42
PULSE_API_TOKEN=your-token pulse actions plan \
--api-url http://localhost:7655 \
--request-id agent-run-123 \
--resource-id vm:42 \
--capability restart \
--param mode=graceful \
--reason "Recover after confirmed outage" \
--requested-by agent:oncall-helper
PULSE_API_TOKEN=your-token pulse actions decide \
--api-url http://localhost:7655 \
--action-id act_... \
--outcome approved \
--reason "Inside maintenance window"
PULSE_API_TOKEN=your-token pulse actions execute \
--api-url http://localhost:7655 \
--action-id act_... \
--reason "Execute approved recovery"
PULSE_API_TOKEN=your-token pulse actions audit \
--api-url http://localhost:7655 \
--resource-id vm:42 \
--limit 10
PULSE_API_TOKEN=your-token pulse actions events \
--api-url http://localhost:7655 \
--action-id act_...Request:
{
"requestId": "agent-run-123",
"resourceId": "vm:42",
"capabilityName": "restart",
"params": { "mode": "graceful" },
"reason": "Recover after confirmed outage",
"requestedBy": "agent:oncall-helper"
}Response:
{
"actionId": "act_...",
"requestId": "agent-run-123",
"allowed": true,
"requiresApproval": true,
"approvalPolicy": "admin",
"predictedBlastRadius": ["vm:42", "node-1"],
"rollbackAvailable": false,
"message": "Plan created for restart on web-42. Execution requires admin approval and is not performed by this endpoint.",
"plannedAt": "2026-05-03T10:00:00Z",
"expiresAt": "2026-05-03T10:05:00Z",
"resourceVersion": "resource:sha256:...",
"policyVersion": "policy:sha256:...",
"planHash": "sha256:...",
"preflight": {
"target": "vm:42",
"currentState": "web-42 is warning",
"intendedChange": "Restart the VM",
"dryRunAvailable": false,
"dryRunSummary": "No provider-supported dry run is advertised for this capability.",
"safetyChecks": [
"Resource was resolved from the unified resource registry.",
"Capability is advertised by the resource contract.",
"This endpoint plans only; it does not approve or execute the action.",
"Execution requires admin approval."
],
"verificationSteps": [
"Refresh the resource and confirm the expected state after execution.",
"Review /api/audit/actions/{actionId}/events for lifecycle evidence."
],
"generatedAt": "2026-05-03T10:00:00Z"
}
}User notes, tags, and custom URLs for resources.
-
GET /api/agents/metadata(admin ormonitoring:read) -
GET /api/agents/metadata/{agentId}(admin ormonitoring:read) -
PUT /api/agents/metadata/{agentId}(admin ormonitoring:write) -
DELETE /api/agents/metadata/{agentId}(admin ormonitoring:write) -
GET /api/guests/metadata(admin ormonitoring:read) -
GET /api/guests/metadata/{guestId}(admin ormonitoring:read) -
PUT /api/guests/metadata/{guestId}(admin ormonitoring:write) -
DELETE /api/guests/metadata/{guestId}(admin ormonitoring:write) -
GET /api/docker/metadata(admin ormonitoring:read) -
GET /api/docker/metadata/{containerId}(admin ormonitoring:read) -
PUT /api/docker/metadata/{containerId}(admin ormonitoring:write) -
DELETE /api/docker/metadata/{containerId}(admin ormonitoring:write) -
GET /api/docker/runtimes/metadata(admin ormonitoring:read) -
GET /api/docker/runtimes/metadata/{runtimeId}(admin ormonitoring:read) -
PUT /api/docker/runtimes/metadata/{runtimeId}(admin ormonitoring:write) -
DELETE /api/docker/runtimes/metadata/{runtimeId}(admin ormonitoring:write)
GET /api/version
Returns version, build time, and update status.
Example response:
{
"version": "6.0.0",
"buildTime": "2026-02-21T00:00:00Z",
"channel": "stable",
"deploymentType": "systemd",
"updateAvailable": false,
"latestVersion": "6.0.0"
}Version fields are returned as plain semantic versions (no leading v).
GET /api/config
Returns a small public config payload (update channel, auto-update enabled).
GET /api/config/nodes
POST /api/config/nodes
{
"type": "pve",
"name": "Proxmox 1",
"host": "https://198.51.100.10:8006",
"user": "root@pam",
"password": "password"
}POST /api/config/nodes/test-connection
Validate credentials before saving.
POST /api/config/nodes/test-config
Validates node config without saving.
PUT /api/config/nodes/{id}
DELETE /api/config/nodes/{id}
POST /api/config/nodes/{id}/test
POST /api/config/nodes/{id}/refresh-cluster
POST /api/config/export (admin or API token)
Request body:
{ "passphrase": "use-a-strong-passphrase" }Returns an encrypted export bundle in data. Passphrases must be at least 12 characters.
POST /api/config/import (admin)
Request body:
{
"data": "<exported-bundle>",
"passphrase": "use-a-strong-passphrase"
}GET /api/setup-script
Returns the Proxmox/PBS setup script as a shell-script download. Accepts an
optional temporary setup token in the setup_token query for embedded
non-interactive bootstrap; otherwise the script prompts for the one-time setup
token at runtime. Canonical callers must send a supported type of pve or
pbs plus non-empty host and pulse_url; the route no longer generates
placeholder-host scripts for later repair or reconstructs Pulse identity from
the request origin. The route now shares the same canonical type boundary as
/api/setup-script-url, rejecting unsupported node types instead of treating
unknown values as PBS, and it normalizes the supplied host before script
generation so downloaded artifacts and rerun URLs preserve the same canonical
node identity as the bootstrap response. The optional backup_perms=true
query is supported only for type=pve.
POST /api/setup-script-url (auth)
Generates a one-time setup token and URL for /api/setup-script.
Canonical callers must send a supported type of pve or pbs plus a
non-empty host; the backend normalizes that host before minting the setup
token and now returns the canonical bootstrap identity back in the response as
type, host, url, downloadURL, scriptFileName, command, commandWithEnv,
commandWithoutEnv, setupToken, tokenHint, and expires. The returned
commands are canonical root-or-sudo curl -fsSL bootstrap commands for the
generated setup script, while url, downloadURL, and scriptFileName are
the runtime-owned artifact metadata used by copy and manual download surfaces.
The request body is a single canonical JSON object only; unknown fields and trailing JSON are
rejected as invalid request shape, and backupPerms:true is supported only for
type:"pve". This route stays on the normal
authenticated bootstrap boundary: when Pulse auth is already configured it
requires a real authenticated session or API token, and setup tokens do not
authorize the request itself. Pulse-managed Proxmox monitor-token names on the
setup/bootstrap path derive from the canonical Pulse endpoint, not request-local
host fallbacks, so setup-script and turnkey node-add flows stay on one
deterministic pulse-<canonical-scope-slug> identity per Pulse instance.
setupToken remains bootstrap transport data for /api/setup-script and
/api/auto-register, while tokenHint is the operator-facing display field
for quick-setup surfaces and must stay masked instead of exposing the full
one-time token in UI copy. Shared frontend consumers may validate
setupToken, but they should not retain or display it once the returned
bootstrap artifact and tokenHint are available; visible quick-setup previews
should use the non-secret commandWithoutEnv form while copy actions keep
using the token-bearing commandWithEnv artifact, and manual download flows
should use the token-bearing downloadURL artifact instead of rebuilding a
plain setup-script URL from non-secret preview state. Non-frontend bootstrap
consumers such as the runtime-side Unified Agent bootstrap flow and shell installer must fail closed on that
same full artifact contract too, rejecting missing or mismatched
downloadURL, tokenHint, or expired expires values instead of accepting a
reduced setup-token-only response shape.
POST /api/auto-register
Registers a node through the canonical /api/auto-register contract using a temporary
setup token carried in the JSON authToken field. Canonical callers must send
a supported type of pve or pbs, an explicit source marker of agent or
script, a canonical Pulse-managed tokenId in the form
pulse-monitor@{pve|pbs}!pulse-<canonical-scope-slug> matching the requested
type, an explicit serverName, and missing-token requests now fail with
Pulse setup token required. Incomplete token completion requests now fail
with tokenId and tokenValue must be provided together, and other missing
canonical request fields fail with explicit Missing required canonical auto-register fields: ... guidance.
Success responses now carry the canonical stored identity and caller boundary
back to the installer or runtime-side Unified Agent:
{"status":"success","action":"use_token","type":"pve|pbs","source":"agent|script","host":"https://...","nodeId":"<stored-name>","nodeName":"<stored-name>",...}.
POST /api/agent-install-command (auth)
Generates an API token and install command for agent-based Proxmox setup.
GET /api/discover (auth)
Runs network discovery.
Service discovery is used by Pulse Assistant and the UI to inventory web services and enrich links.
GET /api/discovery(list summaries)GET /api/discovery/statusPUT /api/discovery/settings(admin,settings:write)GET /api/discovery/type/{type}GET /api/discovery/agent/{agentId}GET /api/discovery/{type}/{targetId}/{resourceId}POST /api/discovery/{type}/{targetId}/{resourceId}(trigger discovery, optionalforce)DELETE /api/discovery/{type}/{targetId}/{resourceId}GET /api/discovery/{type}/{targetId}/{resourceId}/progressPUT /api/discovery/{type}/{targetId}/{resourceId}/notes
POST /api/test-notification (auth)
Broadcasts a WebSocket test event.
GET /api/charts?range=1h
Returns time-series data for CPU, Memory, and Storage.
Ranges: 5m, 15m, 30m, 1h, 4h, 12h, 24h, 7d
GET /api/storage-charts
Returns storage chart data.
GET /api/storage/
Detailed storage usage per node and pool.
Pulse v6 uses the recovery API to provide a platform-agnostic view of backup and snapshot artifacts.
See docs/architecture/RECOVERY_CONTRACT.md for the provider-neutral contract
(subjects, points, rollups, posture, and filter semantics).
GET /api/recovery/points- Query params:
- Core filters:
provider,kind,mode,outcome,subjectResourceId,rollupId - Time window:
from(RFC3339),to(RFC3339) - Paging:
page,limit - Normalized filters:
q,cluster,node,namespace,scope=workload,verification(verified|unverified|unknown)
- Core filters:
- Query params:
GET /api/recovery/rollups- Query params:
provider,kind,mode,outcome,subjectResourceId,rollupId,from(RFC3339),to(RFC3339),page,limit
- Query params:
GET /api/recovery/postures- Returns server-derived per-resource protection posture and provider evidence quality.
- Query params: repeated
resourceIdvalues (maximum 200),state(protected|attention|unprotected|unknown),page,limit(maximum 200) - Batch clients must make one bounded request per 200 resource ids, never one request per table row.
- Unknown identity, permission, history, or collection completeness remains
unknown; clients must not infer a healthier state from raw backup or snapshot artifacts.
GET /api/recovery/series- Returns per-day counts for the activity chart.
- Query params: same filters as
/api/recovery/points(except paging), plustzOffsetMinutes(integer; UTC offset minutes for day bucketing)
GET /api/recovery/facets- Returns distinct filter values (clusters/nodes/namespaces) and capability flags (size/verification/entity id present).
- Query params: same filters as
/api/recovery/points(except paging)
POST /api/notifications/test (admin)
Triggers a test alert to all configured channels.
GET /api/notifications/email(admin)PUT /api/notifications/email(admin)GET /api/notifications/apprise(admin)PUT /api/notifications/apprise(admin)GET /api/notifications/webhooks(admin)POST /api/notifications/webhooks(admin)PUT /api/notifications/webhooks/<id>(admin)DELETE /api/notifications/webhooks/<id>(admin)POST /api/notifications/webhooks/test(admin)GET /api/notifications/webhook-templates(admin)GET /api/notifications/webhook-history(admin)GET /api/notifications/email-providers(admin)GET /api/notifications/health(admin)
GET /api/admin/webhooks/audit(admin,settings:read)POST /api/admin/webhooks/audit(admin,settings:write)- Body:
{ "urls": ["https://..."] } - Strict JSON contract: unknown fields and trailing payload are rejected.
- Maximum
20webhook URLs per update request. - URLs are normalized (trimmed) and duplicate entries are ignored.
- Endpoint fails closed if URL validation runtime is unavailable.
- Body:
GET /api/admin/reports/catalog(admin,settings:read)- Returns the canonical reporting catalog for the settings surface, including locked-state teaser copy, enabled-surface guidance copy, performance-report options, canonical single-report filename subject, canonical fallback filename date style, and the nested VM inventory export definition.
- Metadata route: readable without the
advanced_reportingfeature so locked admin surfaces can render the same reporting definition before upsell.
GET /api/admin/reports/generate(admin,settings:read)- Query params:
format(pdf/csv, defaultpdf),resourceType,resourceId,metricType(optional),start/end(RFC3339, optional; defaults to last 24h),title(optional) - If
titleis omitted, the backend applies the canonical default title for that resource report.
- Query params:
POST /api/admin/reports/generate-multi(admin,settings:read)- Body fields:
resources(1-50 entries of{resourceType,resourceId}),format,metricType(optional),start/end(RFC3339, optional; defaults to last 24h),title(optional) - If
titleis omitted, the backend applies the canonical default fleet report title.
- Body fields:
GET /api/admin/reports/inventory/vms/export(admin,settings:read)- Query params:
format(csvonly; optional and defaults tocsv) - Exports the current fleet-wide VM inventory as spreadsheet-friendly CSV using the canonical runtime model.
- Query params:
Validation and limits:
startandendmust be RFC3339 when provided.- Malformed
start/endvalues,endnot strictly afterstart, or report windows over 366 days return400 invalid_time_range. metricTypemust match[a-zA-Z0-9._:-]+and be <= 64 chars, otherwise400 invalid_metric_type.titlemust be <= 256 chars, otherwise400 invalid_title.- Multi-report body max size is 1MB; oversized payloads return
400 body_too_large. - Multi-report bodies reject trailing payload and unknown JSON fields with
400 invalid_body. - VM inventory export only accepts
csv.
Common reporting error codes:
invalid_format,missing_params,invalid_resource_type,invalid_resource_idinvalid_metric_type,invalid_title,invalid_time_rangeno_resources,too_many_resources,body_too_large,invalid_body
GET /api/notifications/queue/stats(admin)GET /api/notifications/dlq(admin)POST /api/notifications/dlq/retry(admin)POST /api/notifications/dlq/delete(admin)
Alert configuration and history (requires monitoring:read/monitoring:write).
GET /api/alerts/configPUT /api/alerts/configPOST /api/alerts/activateGET /api/alerts/activeGET /api/alerts/delivery-diagnosis?alertIdentifier=<alert-id>GET /api/alerts/historyDELETE /api/alerts/historyGET /api/alerts/incidentsPOST /api/alerts/incidents/notePOST /api/alerts/bulk/acknowledgePOST /api/alerts/bulk/clearPOST /api/alerts/acknowledge(body:{ "id": "alert-id" })POST /api/alerts/unacknowledge(body:{ "id": "alert-id" })POST /api/alerts/clear(body:{ "id": "alert-id" })
GET /api/security/status
Returns authentication status, proxy auth state, and security posture flags.
POST /api/security/change-password
{ "currentPassword": "old-pass", "newPassword": "new-pass" }In Docker installs, the response includes a restart notice.
GET /api/security/tokens
POST /api/security/tokens
{ "name": "ansible-script", "scopes": ["monitoring:read"] }DELETE /api/security/tokens/<id>
POST /api/security/recovery
Supports actions:
generate_token(localhost only)disable_authenable_auth
GET /api/security/recovery returns recovery mode status.
POST /api/security/reset-lockout
{ "identifier": "admin" }Identifier can be a username or IP address.
POST /api/security/regenerate-token
Returns a new raw token (shown once) and updates stored hashes:
{
"success": true,
"token": "raw-token",
"deploymentType": "systemd",
"requiresRestart": false,
"message": "New API token generated and active immediately! Save this token - it won't be shown again."
}
---
## 🧾 Audit Log (Pro)
These endpoints require admin access and the `settings:read` scope. On Community, the list endpoint returns an empty set and `persistentLogging: false`.
### List Audit Events
`GET /api/audit?limit=100&event=login&user=admin&success=true&startTime=2024-01-01T00:00:00Z&endTime=2024-01-31T23:59:59Z`
Response:
```json
{
"events": [
{
"id": "6b3c9c3c-9a2f-4b3c-9a3b-3d0e8c5c5d45",
"timestamp": "2024-01-12T10:15:30Z",
"event": "login",
"user": "admin",
"ip": "198.51.100.10",
"path": "/api/login",
"success": true,
"details": "Successful login",
"signature": "..."
}
],
"total": 1,
"persistentLogging": true
}GET /api/audit/<id>/verify
Response:
{
"available": true,
"verified": true,
"message": "Event signature verified"
}POST /api/security/validate-token
{ "token": "raw-token" }Returns:
{ "valid": true, "message": "Token is valid" }POST /api/security/validate-bootstrap-token
Provide the token via header X-Setup-Token or JSON body:
{ "token": "bootstrap-token" }Returns 204 No Content on success.
POST /api/security/quick-setup
Requires a valid bootstrap token (header X-Setup-Token) or an authenticated session.
{
"username": "admin",
"password": "StrongPass!1",
"apiToken": "token",
"enableNotifications": false,
"darkMode": false,
"force": false,
"setupToken": "optional-bootstrap-token"
}POST /api/security/apply-restart
Applies auth changes by restarting the service (systemd deployments only).
GET /api/system/settings
Retrieve current system settings.
POST /api/system/settings/update
Update system settings. Requires admin + settings:write.
GET /api/config/system
Legacy system settings endpoint (read-only).
GET /api/system/mock-mode
POST /api/system/mock-mode
PUT /api/system/mock-mode
Enable or disable mock data generation (dev/demo only).
POST /api/system/ssh-config
Writes the SSH config used for temperature collection (requires setup token or auth).
POST /api/system/verify-temperature-ssh
Tests SSH connectivity for temperature collection (requires setup token or auth).
GET /api/monitoring/scheduler/health
Returns scheduler health, DLQ, and breaker status. Requires monitoring:read.
GET /api/updates/checkPOST /api/updates/applyGET /api/updates/statusGET /api/updates/streamGET /api/updates/plan?version=X.Y.Z(optionalchannel, acceptsvprefix)GET /api/updates/historyGET /api/updates/history/entry?id=<event_id>
GET /api/infra-updates(requiresmonitoring:read)GET /api/infra-updates/summary(requiresmonitoring:read)POST /api/infra-updates/check(requiresmonitoring:write)GET /api/infra-updates/agent/{agentId}(requiresmonitoring:read)GET /api/infra-updates/{resourceId}(requiresmonitoring:read)
GET /api/diagnostics(auth)POST /api/diagnostics/docker/prepare-token(admin,settings:write)
GET /api/logs/stream(server-sent stream)GET /api/logs/download(bundled logs)GET /api/logs/levelPOST /api/logs/level(set log level)
GET /api/server/info
Returns minimal server info for installer scripts.
GET /api/oidc/{providerID}/loginGET /api/oidc/{providerID}/callback
OIDC and SAML configuration is managed via SSO providers.
GET /api/security/sso/providers(admin)POST /api/security/sso/providers(admin)GET /api/security/sso/providers/{id}(admin)PUT /api/security/sso/providers/{id}(admin)DELETE /api/security/sso/providers/{id}(admin)
Provider mutation request contract:
- Max request body: 1MB.
- Strict JSON contract: unknown fields and trailing payload are rejected.
- Provider IDs must match server validation.
- OIDC and SAML providers are included with the Community SSO entitlement.
POST /api/security/sso/providers/test(admin)POST /api/security/sso/providers/metadata/preview(admin)
Test/preview request contract:
- Max request body: 32KB.
- Strict JSON contract: unknown fields and trailing payload are rejected.
- Common errors include
invalid_json,validation_error,rate_limited,body_too_large.
GET /api/license/status
GET /api/license/features
POST /api/license/activate
{ "license_key": "PASTE_KEY_HERE" }POST /api/license/clear
Role-based access control endpoints for managing roles and user assignments. Requires admin access and the rbac license feature.
GET /api/admin/roles
Returns all defined roles.
POST /api/admin/roles
{
"id": "operator",
"name": "Operator",
"description": "Can view and manage alerts",
"permissions": [
{ "action": "read", "resource": "alerts" },
{ "action": "write", "resource": "alerts" }
]
}PUT /api/admin/roles/{id}
Update an existing role's name, description, or permissions.
DELETE /api/admin/roles/{id}
GET /api/admin/users
Returns all users with their role assignments.
POST /api/admin/users/{username}/roles
{ "role_id": "operator" }DELETE /api/admin/users/{username}/roles/{role_id}
Note: OIDC group-to-role mapping can automatically assign roles on login. See OIDC.md for configuration.
Multi-tenant organization management. Requires PULSE_MULTI_TENANT_ENABLED=true and an Enterprise license with the multi_tenant feature. All endpoints require authentication.
See MULTI_TENANT.md for setup and architecture details.
GET /api/orgs (requires settings:read)
Returns organizations accessible to the authenticated user.
POST /api/orgs (requires settings:write, session auth only)
{ "id": "acme-corp", "displayName": "Acme Corporation" }The creator becomes the owner and first member. Organization IDs must be lowercase alphanumeric with hyphens, 3-64 characters.
GET /api/orgs/{id} (requires settings:read)
Returns organization details. User must be a member.
PUT /api/orgs/{id} (requires settings:write, session auth only)
{ "displayName": "Updated Name" }Admin or owner role required. The default organization cannot be updated.
DELETE /api/orgs/{id} (requires settings:write, session auth only)
Admin or owner role required. The default organization cannot be deleted.
GET /api/orgs/{id}/members (requires settings:read)
Returns all members with their roles. User must be a member of the org.
POST /api/orgs/{id}/members (requires settings:write, session auth only)
{ "userId": "jane", "role": "editor" }Roles: owner, admin, editor, viewer. Admin or owner role required. Setting role to owner transfers ownership (only current owner can do this). Default org members cannot be managed.
DELETE /api/orgs/{id}/members/{userId} (requires settings:write, session auth only)
Admin or owner role required. The organization owner cannot be removed.
GET /api/orgs/{id}/shares (requires settings:read)
Returns resources shared outbound from this organization to others.
GET /api/orgs/{id}/shares/incoming (requires settings:read)
Returns resources shared inbound to this organization from other organizations.
POST /api/orgs/{id}/shares (requires settings:write, session auth only)
{
"targetOrgId": "partner-org",
"resourceType": "vm",
"resourceId": "vm-101",
"resourceName": "Web Server",
"accessRole": "viewer"
}Share a resource with another organization. Valid resource types: vm, container, agent, storage, pbs, pmg. Access roles: viewer, editor, admin. Admin or owner role required on the source org.
DELETE /api/orgs/{id}/shares/{shareId} (requires settings:write, session auth only)
Revoke a resource share. Admin or owner role required.
Paid gating: endpoints labeled with a paid plan require the relevant Relay, Pro, legacy Pro+, or Cloud capability and return 402 Payment Required if the feature is not licensed.
GET /api/settings/ai
Returns current AI configuration (providers, models, patrol status). Requires admin + settings:read.
PUT /api/settings/ai/update (or POST /api/settings/ai/update)
Configure AI providers, API keys, and preferences. Requires admin + settings:write.
GET /api/ai/models
Lists models available to the configured providers (queried live from provider APIs).
POST /api/ai/testPOST /api/ai/test/{provider}
Anthropic subscription OAuth is unsupported. These routes remain only for fail-closed compatibility and token cleanup:
POST /api/ai/oauth/start(admin): returns501withunsupported_anthropic_oauthPOST /api/ai/oauth/exchange(admin): returns501withunsupported_anthropic_oauthGET /api/ai/oauth/callback(public): redirects to settings withai_oauth_error=unsupportedunless the provider supplied a specific errorPOST /api/ai/oauth/disconnect(admin): clears stored legacy OAuth tokens
POST /api/ai/execute
Runs an AI request which may return tool calls, findings, or suggested actions.
POST /api/ai/execute/stream
Streaming variant of execute (used by the UI for incremental responses).
GET /api/ai/statusPOST /api/ai/chat(streaming)GET /api/ai/sessionsreturns session summaries; scoped Assistant handoffs may include a safehandoff_summarymarker without model-only context text or command payloads.POST /api/ai/sessionsDELETE /api/ai/sessions/{id}GET /api/ai/sessions/{id}/messagesPOST /api/ai/sessions/{id}/abortPOST /api/ai/sessions/{id}/summarizePOST /api/ai/sessions/{id}/fork- Legacy OpenCode-style file-change routes (
GET /api/ai/sessions/{id}/diff,POST /api/ai/sessions/{id}/revert,POST /api/ai/sessions/{id}/unrevert) return501 Not Implemented; Pulse Assistant sessions do not own file diffs or file-level revert.
POST /api/ai/question/{id}/answer
POST /api/ai/kubernetes/analyze
{ "cluster_id": "cluster-id" }Requires Pro, legacy Pro+, or Cloud with the kubernetes_ai feature enabled. This route remains
available for compatibility, but current v6 Pulse Pro marketing does not treat
Kubernetes-specific analysis as a standalone plan pillar.
POST /api/ai/investigate-alert
Runs a focused investigation for an alert payload (used by the UI).
GET /api/ai/patrol/attention- Returns the typed Patrol attention queue projected from canonical operational lifecycle records. This is the active-count and queue source used by both navigation and Patrol.
- Query params:
filter(active|open|acknowledged|suppressed|stale_unknown|resolved|all),page(minimum 1), andlimit(1–200). - The response includes
data, a lifecycle-widesummary, and bounded paginationmeta. Protection context is joined in one bounded batch, not fetched per item.
GET /api/ai/patrol/attention/summary- Returns the canonical active, open, acknowledged, suppressed,
stale/unknown, and recent-resolved counts plus
calm,coverageState, andevaluatedAt. - A lifecycle-read failure returns a typed unavailable error. It never returns a synthetic zero or healthy state.
- Returns the canonical active, open, acknowledged, suppressed,
stale/unknown, and recent-resolved counts plus
GET /api/ai/patrol/attention/{id}- Returns one attention item with its operational record, lifecycle timeline, typed evidence, recommended next step, relationships, and protection posture.
GET /api/ai/patrol/attention/{id}/evidence/{evidenceId}- Returns one exact retained evidence envelope with its current freshness.
- Returns
410 attention_evidence_detail_expiredwhen the operational record still links the ID but the bounded detail has expired.
POST /api/ai/patrol/attention/{id}/acknowledgePOST /api/ai/patrol/attention/{id}/unacknowledgePOST /api/ai/patrol/attention/{id}/suppress- Body:
{ "reason": "...", "expiresAt": "<RFC3339>" }. - The expiry must be in the future and no more than 30 days away.
- Body:
POST /api/ai/patrol/attention/{id}/unsuppressPOST /api/ai/patrol/attention/{id}/actions/restart/plan- Creates or replays the one server-owned Docker restart plan attached to this operational record and its exact evidence IDs.
- Requires the canonical action authorization, an eligible server-side
offer, and the Pulse Pro
ai_autofixentitlement. Clients cannot supply command authority or override the target.
- Attention reads require
monitoring:read; lifecycle mutations requiremonitoring:write. Action decision and execution use/api/actionsand retain their existing action-specific scopes. - Attention IDs and evidence IDs are opaque and can contain slashes. Clients must path-escape each ID.
GET /api/ai/patrol/autonomyPUT /api/ai/patrol/autonomyGET /api/ai/patrol/statusGET /api/ai/patrol/findingsDELETE /api/ai/patrol/findings(clear all findings)GET /api/ai/patrol/historyGET /api/ai/patrol/runsGET /api/ai/patrol/stream(Pro)POST /api/ai/patrol/run(admin, Pro)POST /api/ai/patrol/acknowledge(Pro)POST /api/ai/patrol/dismissPOST /api/ai/patrol/findings/notePOST /api/ai/patrol/resolvePOST /api/ai/patrol/snooze(Pro)POST /api/ai/patrol/suppress(Pro)GET /api/ai/patrol/suppressions(Pro)POST /api/ai/patrol/suppressions(Pro)DELETE /api/ai/patrol/suppressions/{id}(Pro)GET /api/ai/patrol/dismissed(Pro)
GET /api/ai/unified/findingsGET /api/ai/findings/{id}/investigationGET /api/ai/findings/{id}/investigation/messagesPOST /api/ai/findings/{id}/reinvestigatePOST /api/ai/findings/{id}/reapprove(Pro)
GET /api/ai/approvalsGET /api/ai/approvals/{id}POST /api/ai/approvals/{id}/approvePOST /api/ai/approvals/{id}/denyPOST /api/ai/run-command(execute an approved command)GET /api/ai/agents(connected agents via/api/agent/ws)
GET /api/ai/remediation/plansGET /api/ai/remediation/plan?plan_id=<id>POST /api/ai/remediation/approvePOST /api/ai/remediation/executePOST /api/ai/remediation/rollback
Request bodies:
approve:{ "plan_id": "...", "approved_by": "api" }execute:{ "execution_id": "..." }rollback:{ "execution_id": "..." }
GET /api/ai/intelligenceGET /api/ai/intelligence/patternsGET /api/ai/intelligence/predictionsGET /api/ai/intelligence/correlationsGET /api/ai/intelligence/changes(canonical unified-resource timeline first, patrol-local memory fallback)GET /api/ai/intelligence/baselinesGET /api/ai/intelligence/remediationsGET /api/ai/intelligence/anomaliesGET /api/ai/intelligence/learningGET /api/ai/forecast(params:resource_id,metric, optionalresource_name,horizon_hours,threshold)GET /api/ai/forecasts/overview(params:metric,horizon_hours,threshold)GET /api/ai/learning/preferences(optionalresource_id)GET /api/ai/proxmox/eventsGET /api/ai/proxmox/correlationsGET /api/ai/incidents(optionalresource_id,limit)GET /api/ai/incidents/{resourceId}(optionallimit)GET /api/ai/circuit/status
GET /api/ai/knowledge?guest_id=<id>POST /api/ai/knowledge/savePOST /api/ai/knowledge/deleteGET /api/ai/knowledge/export?guest_id=<id>POST /api/ai/knowledge/importPOST /api/ai/knowledge/clear
GET /api/ai/debug/context(admin)
GET /api/ai/cost/summaryPOST /api/ai/cost/reset(admin)GET /api/ai/cost/export(admin)
Auth required: monitoring:read.
GET /api/metrics-store/stats
Returns stats for the persistent metrics store (SQLite-backed).
GET /api/metrics-store/history
Returns historical metric series for a resource and time range.
Query params:
resourceType(required):node,vm,container,storage,dockerHost,dockerContainerresourceId(required)metric(optional):cpu,memory,disk, etc. Omit for all metricsrange(optional):1h,6h,12h,24h,1d,7d,30d,90d(default24h; duration strings also accepted)maxPoints(optional): Downsample to a target number of points
License: Requests beyond Community's
7dfloor require the paidlong_term_metricsentitlement. Relay unlocks14d, Pro and legacy Pro+ unlock90d, and requests beyond the active tier's limit return402 Payment Required. Aliases:guest(VM/LXC) anddocker(Docker container) are accepted, but persistent store data uses the canonical types above.
GET /download/pulse-agent
Downloads the unified agent binary. Without arch, Pulse serves the local binary on the server host.
Optional query:
?arch=linux-amd64(supported:linux-amd64,linux-arm64,linux-armv7,linux-armv6,linux-386,darwin-amd64,darwin-arm64,freebsd-amd64,freebsd-arm64,windows-amd64,windows-arm64,windows-386)
The response includes X-Checksum-Sha256 for verification.
The unified agent combines host, Docker, and Kubernetes monitoring. Use --enable-docker or --enable-kubernetes to enable additional metrics.
See UNIFIED_AGENT.md for installation instructions.
GET /api/agent/version
Returns the current server version for agent update checks.
GET /api/agents/diagnostics (admin, settings:read)
Returns read-only fleet triage for reported host, Docker / Podman, and Kubernetes agents, including liveness, version drift, profile deployment drift, identity-split evidence, and supported repair handoff hints. It does not enqueue remote actions.
GET /install.sh
Serves the universal install.sh used to install pulse-agent on target machines.
GET /install.ps1
Serves the PowerShell installer for Windows.
POST /api/agents/agent/report - Agent metrics
POST /api/agents/docker/report - Docker container metrics
POST /api/agents/kubernetes/report - Kubernetes cluster metrics
GET /api/agents/agent/lookup?id=<agent_id>
GET /api/agents/agent/lookup?hostname=<hostname>
Looks up an agent by ID or hostname/display name. Requires agent:report.
POST /api/agents/agent/uninstall
Agent self-unregister during uninstall. Requires agent:report.
POST /api/agents/agent/unlink (admin, agent:manage)
Unlinks an agent from a node.
DELETE /api/agents/agent/{agent_id} (admin, agent:manage)
Removes an agent from state.
POST /api/agents/agent/link(admin,agent:manage)POST /api/agents/agent/unlink(admin,agent:manage)
GET /api/agents/agent/{agent_id}/config
Returns the server-side config payload for an agent (used by remote config and debugging). Requires agent:config:read.
The config object includes the merged desired settings, command enablement
decision, and desired-config metadata. When signing is configured, the
signature remains backward-compatible with legacy agents: it covers
agentId, commandsEnabled, settings, issuedAt, and expiresAt.
desiredConfig is computed from the signed command decision plus the
agent-applied settings keys and returned as tamper-evident metadata for newer
clients to recompute and compare.
{
"success": true,
"agentId": "agent-123",
"config": {
"commandsEnabled": true,
"settings": {
"enable_docker": true
},
"desiredConfig": {
"version": "host-agent-config/v1",
"hash": "sha256:..."
},
"issuedAt": "2026-05-13T17:00:00Z",
"expiresAt": "2026-05-13T17:15:00Z",
"signature": "..."
}
}PATCH /api/agents/agent/{agent_id}/config (admin, agent:manage)
Updates server-side config for an agent (e.g., commandsEnabled).
These routes manage Docker / Podman telemetry and container actions reported by the Docker / Podman module inside the installed pulse-agent binary.
POST /api/agents/docker/commands/{commandId}/ack(docker:report)DELETE /api/agents/docker/runtimes/{agentId}(docker:manage, supports?hide=trueor?force=true)POST /api/agents/docker/runtimes/{agentId}/allow-reenroll(docker:manage)PUT /api/agents/docker/runtimes/{agentId}/unhide(docker:manage)PUT /api/agents/docker/runtimes/{agentId}/pending-uninstall(docker:manage)PUT /api/agents/docker/runtimes/{agentId}/display-name(docker:manage)POST /api/agents/docker/runtimes/{agentId}/check-updates(docker:manage)POST /api/agents/docker/runtimes/{agentId}/update-all(docker:manage)POST /api/agents/docker/containers/update(docker:manage)
DELETE /api/agents/kubernetes/clusters/{clusterId}(kubernetes:manage, supports?hide=trueor?force=true)POST /api/agents/kubernetes/clusters/{clusterId}/allow-reenroll(kubernetes:manage)PUT /api/agents/kubernetes/clusters/{clusterId}/unhide(kubernetes:manage)PUT /api/agents/kubernetes/clusters/{clusterId}/pending-uninstall(kubernetes:manage)PUT /api/agents/kubernetes/clusters/{clusterId}/display-name(kubernetes:manage)
GET /api/admin/profiles (admin, Pro)
POST /api/admin/profiles (admin, Pro)
GET /api/admin/profiles/{id} (admin, Pro)
PUT /api/admin/profiles/{id} (admin, Pro)
DELETE /api/admin/profiles/{id} (admin, Pro)
GET /api/admin/profiles/schema (admin, Pro)
POST /api/admin/profiles/validate (admin, Pro)
POST /api/admin/profiles/suggestions (admin, Pro)
GET /api/admin/profiles/changelog (admin, Pro)
GET /api/admin/profiles/deployments (admin, Pro)
POST /api/admin/profiles/deployments (admin, Pro)
GET /api/admin/profiles/{id}/versions (admin, Pro)
POST /api/admin/profiles/{id}/rollback/{version} (admin, Pro)
GET /api/admin/profiles/assignments (admin, Pro)
POST /api/admin/profiles/assignments (admin, Pro)
DELETE /api/admin/profiles/assignments/{agent_id} (admin, Pro)
Agentless availability checks monitor endpoint-only devices and services with ICMP ping, TCP port, HTTP, or HTTPS probes. They are managed from Settings -> Monitoring -> Availability checks and are also exposed through the API for automation.
GET /api/availability-targets(settings:read) - List configured targets and latest probe status.POST /api/availability-targets(settings:write) - Add a target.PUT /api/availability-targets/{id}(settings:write) - Update a target.DELETE /api/availability-targets/{id}(settings:write) - Remove a target.POST /api/availability-targets/test(settings:write) - Test an unsaved target.POST /api/availability-targets/{id}/test(settings:write) - Test a saved target.
Target payload fields:
name- Display name.targetKind-machine,service, ordevice; defaults toservice.address- Hostname, IP address, or URL.protocol-icmp,tcp,http, orhttps. The input aliaspingis accepted and is stored/returned as canonicalicmp.port- Required fortcp, optional forhttp/https, and omitted foricmp.path- Optional HTTP path.enabled- Whether the target is scheduled.pollIntervalSeconds- Minimum 10 seconds; defaults to 60.timeoutMillis- Minimum 250 milliseconds; defaults to 2000.failureThreshold- Number of consecutive failures before alerting; defaults to 2.linkedResourceId- Optional resource id hint for attaching the probe facet to an existing resource.
An explicit linkedResourceId is authoritative and fails closed when it
cannot resolve. Without it, Pulse attaches only on one exact normalized IP or
hostname match. Zero matches remain standalone and multiple matches remain
ambiguous; Pulse does not guess.
Example ping-only target:
{
"name": "Garage temperature sensor",
"targetKind": "device",
"address": "garage-sensor.local",
"protocol": "ping",
"enabled": true
}The create response and subsequent reads return "protocol": "icmp".
TrueNAS connection management endpoints for adding, testing, and removing TrueNAS SCALE/CORE instances.
GET /api/truenas/connections(admin,settings:read) — List configured TrueNAS connections.POST /api/truenas/connections(admin,settings:write) — Add a new TrueNAS connection.POST /api/truenas/connections/test(admin,settings:write) — Test a TrueNAS connection before saving.DELETE /api/truenas/connections/{id}(admin,settings:write) — Remove a TrueNAS connection.
TrueNAS resources (pools, datasets, disks, ZFS snapshots, replication tasks, alerts) are surfaced through the unified /api/resources endpoint with source=truenas.
End-to-end encrypted relay protocol for mobile connectivity.
Relay pairing endpoints generate the QR code and deep link used by supported Pulse Mobile clients.
GET /api/settings/relay(admin,settings:read, Relay+) — Get current relay configuration.PUT /api/settings/relay(admin,settings:write, Relay+) — Update relay configuration.GET /api/settings/relay/status(admin,settings:read, Relay+) — Get relay connection status.
GET /api/onboarding/qr(settings:read) — Generate QR code for Pulse Mobile pairing.POST /api/onboarding/validate(settings:read) — Validate a mobile onboarding connection.GET /api/onboarding/deep-link(settings:read) — Generate deep-link URL for mobile app.
GET /ws– Primary UI WebSocket (browser sessions).GET /api/agent/ws– Agent WebSocket used for AI command execution.
Note: This is a summary of the most common endpoints. For a complete list, inspect the network traffic of the Pulse dashboard or check the source code in
internal/api/router.go.