Files
Pulse/docs/API.md
rcourtman a1dc451ed4 Document alert reliability features and DLQ API
Add comprehensive documentation for new alert system reliability features:

**API Documentation (docs/API.md):**
- Dead Letter Queue (DLQ) API endpoints
  - GET /api/notifications/dlq - Retrieve failed notifications
  - GET /api/notifications/queue/stats - Queue statistics
  - POST /api/notifications/dlq/retry - Retry DLQ items
  - POST /api/notifications/dlq/delete - Delete DLQ items
- Prometheus metrics endpoint documentation
  - 18 metrics covering alerts, notifications, and queue health
  - Example Prometheus configuration
  - Example PromQL queries for common monitoring scenarios

**Configuration Documentation (docs/CONFIGURATION.md):**
- Alert TTL configuration
  - maxAlertAgeDays, maxAcknowledgedAgeDays, autoAcknowledgeAfterHours
- Flapping detection configuration
  - flappingEnabled, flappingWindowSeconds, flappingThreshold, flappingCooldownMinutes
- Usage examples and common scenarios
- Best practices for preventing notification storms

All new features are fully documented with examples and default values.
2025-11-06 17:34:05 +00:00

1472 lines
41 KiB
Markdown

# Pulse API Documentation
## Overview
Pulse provides a REST API for monitoring and managing Proxmox VE and PBS instances. All API endpoints are prefixed with `/api`.
## Authentication
Pulse supports multiple authentication methods that can be used independently or together:
> **Service name note:** Systemd deployments use `pulse.service`. If your host still uses the legacy `pulse-backend.service`, substitute that name in the commands below.
### Password Authentication
Set a username and password for web UI access. Passwords are hashed with bcrypt (cost 12) for security.
```bash
# Systemd
sudo systemctl edit pulse
# Add:
[Service]
Environment="PULSE_AUTH_USER=admin"
Environment="PULSE_AUTH_PASS=your-secure-password"
# Docker
docker run -e PULSE_AUTH_USER=admin -e PULSE_AUTH_PASS=your-password rcourtman/pulse:latest
```
Once set, users must login via the web UI. The password can be changed from Settings → Security.
### API Token Authentication
For programmatic API access and automation. Manage tokens via **Settings → Security → API tokens** or the `/api/security/tokens` endpoints.
**API-Only Mode**: If at least one API token is configured (no password auth), the UI remains accessible in read-only mode while API modifications require a valid token.
```bash
# Systemd
sudo systemctl edit pulse
# Add:
[Service]
Environment="API_TOKENS=token-a,token-b"
# Docker
docker run -e API_TOKENS=token-a,token-b rcourtman/pulse:latest
```
### Using Authentication
```bash
# With API token (header)
curl -H "X-API-Token: your-secure-token" http://localhost:7655/api/health
# With API token (Authorization header)
curl -H "Authorization: Bearer your-secure-token" http://localhost:7655/api/health
# (Query parameters are rejected to avoid leaking tokens in logs or referrers.)
# With session cookie (after login)
curl -b cookies.txt http://localhost:7655/api/health
```
> Legacy note: The `API_TOKEN` environment variable is still honored for backwards compatibility. When both `API_TOKEN` and `API_TOKENS` are supplied, Pulse merges them and prefers the newest token when presenting hints.
### Security Features
When authentication is enabled, Pulse provides enterprise-grade security:
- **CSRF Protection**: All state-changing requests require a CSRF token
- **Rate Limiting** (enhanced in v4.24.0): 500 req/min general, 10 attempts/min for authentication
- **New**: All responses include rate limit headers:
- `X-RateLimit-Limit`: Maximum requests per window
- `X-RateLimit-Remaining`: Requests remaining in current window
- `X-RateLimit-Reset`: Unix timestamp when the limit resets
- `Retry-After`: Seconds to wait before retrying (on 429 responses)
- **Account Lockout**: Locks after 5 failed attempts (15 minute cooldown) with clear feedback
- **Secure Sessions**: HttpOnly cookies, 24-hour expiry
- **Security Headers**: CSP, X-Frame-Options, X-Content-Type-Options, etc.
- **Audit Logging**: All security events are logged
### CSRF Token Usage
When using session authentication, include the CSRF token for state-changing requests:
```javascript
// Get CSRF token from cookie
const csrfToken = getCookie('pulse_csrf');
// Include in request header
fetch('/api/nodes', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
```
## Common Response Headers
Most endpoints emit a pair of diagnostic headers to help with troubleshooting:
- `X-Request-ID` — unique identifier assigned to each HTTP request. The same value appears in Pulse logs, enabling quick correlation when raising support tickets or hunting through log files.
- `X-RateLimit-*` family (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `Retry-After`) — surfaced when rate limiting is enabled (default in v4.24.0+).
- `X-Diagnostics-Cached-At` — returned only by `/api/diagnostics`; indicates when the current diagnostics payload was generated.
## Core Endpoints
### Health Check
Check if Pulse is running and healthy.
```bash
GET /api/health
```
Response:
```json
{
"status": "healthy",
"timestamp": 1754995749,
"uptime": 166.187561244
}
```
**Optional fields** (v4.24.0+, appear when relevant):
```json
{
"status": "healthy",
"timestamp": 1754995749,
"uptime": 166.187561244,
"proxyInstallScriptAvailable": true,
"devModeSSH": false
}
```
### Version Information
Get current Pulse version and build info.
```bash
GET /api/version
```
Response (v4.24.0+):
```json
{
"version": "v4.24.0",
"build": "release",
"buildTime": "2025-10-20T10:30:00Z",
"runtime": "go",
"goVersion": "1.23.2",
"channel": "stable",
"deploymentType": "systemd",
"isDocker": false,
"isDevelopment": false,
"updateAvailable": false,
"latestVersion": "v4.24.0"
}
```
### System State
Get complete system state including all nodes and their metrics.
```bash
GET /api/state
```
Response payload includes dedicated collections for each subsystem:
- `nodes`: Proxmox VE nodes with live resource metrics and connection health
- `vms` / `containers`: Guest workloads with CPU, memory, disk, network, and power state
- `dockerHosts`: Hosts that report through the Docker agent, including container inventory
- Each host entry includes `issues` (restart loops, health check failures), `lastSeen`, `agentVersion`, and a flattened list of labelled containers so you can display the same insights the UI shows.
- `storage`: Per-node storage with capacity and usage metadata
- `cephClusters`: Ceph health summaries, daemon counts, and pool capacity (see below)
- `physicalDisks`: SMART/enclosure telemetry when physical disk monitoring is enabled
- `pbs`: Proxmox Backup Server inventory, job status, and datastore utilisation
- `pmg`: Proxmox Mail Gateway health and analytics (mail totals, queues, spam distribution)
- `pveBackups` / `pbsBackups`: Backup history across snapshots, storage jobs, and PBS
- `stats`: System-wide aggregates (uptime, versions, counts)
- `activeAlerts`: Currently firing alerts with hysteresis-aware metadata
- `performance`: Cached chart series for the dashboard
#### Ceph Cluster Data
When Pulse detects Ceph-backed storage (RBD, CephFS, etc.), the `cephClusters` array surfaces detailed health information gathered via `/cluster/ceph/status` and `/cluster/ceph/df`:
```json
{
"cephClusters": [
{
"id": "pve-cluster-4f7c...",
"instance": "pve-cluster",
"health": "HEALTH_OK",
"healthMessage": "All OSDs are running",
"totalBytes": 128178802368000,
"usedBytes": 87236608000000,
"availableBytes": 40942194432000,
"usagePercent": 68.1,
"numMons": 3,
"numMgrs": 2,
"numOsds": 12,
"numOsdsUp": 12,
"numOsdsIn": 12,
"numPGs": 768,
"pools": [
{ "id": 1, "name": "cephfs_data", "storedBytes": 7130316800000, "availableBytes": 1239814144000, "objects": 1024, "percentUsed": 64.2 }
],
"services": [
{ "type": "mon", "running": 3, "total": 3 },
{ "type": "mgr", "running": 2, "total": 2 }
],
"lastUpdated": 1760219854
}
]
}
```
Each service entry lists offline daemons in `message` when present (for example, `Offline: mgr.x@pve2`), making it easy to highlight degraded components in custom tooling.
### Scheduler Health
Monitor Pulse's internal adaptive polling scheduler and circuit breaker status.
```bash
GET /api/monitoring/scheduler/health
```
This endpoint provides detailed metrics about:
- Task queue depths and processing times
- Circuit breaker states per node
- Backoff delays and retry schedules
- Dead-letter queue entries (tasks that repeatedly fail)
- Instance-level staleness tracking
See [Scheduler Health API Documentation](api/SCHEDULER_HEALTH.md) for complete response schema and examples.
**Key use cases:**
- Monitor for polling backlogs
- Detect connectivity issues via circuit breaker trips
- Track node health and responsiveness
- Identify failing tasks in the dead-letter queue
#### PMG Mail Gateway Data
When PMG instances are configured, the `pmg` array inside `/api/state` surfaces consolidated health and mail analytics for each gateway:
- `status`/`connectionHealth` reflect reachability (`online` + `healthy` when the API responds).
- `nodes` lists discovered cluster members and their reported role.
- `mailStats` contains rolling totals for the configured timeframe (default: last 24 hours).
- `mailCount` provides hourly buckets for the last day; useful for charting trends.
- `spamDistribution` captures spam score buckets as returned by PMG.
- `quarantine` aggregates queue counts for spam and virus categories.
Snippet:
```json
{
"pmg": [
{
"id": "pmg-primary",
"name": "primary",
"host": "https://pmg.example.com",
"status": "online",
"version": "8.3.1",
"connectionHealth": "healthy",
"lastSeen": "2025-10-10T09:30:00Z",
"lastUpdated": "2025-10-10T09:30:05Z",
"nodes": [
{ "name": "pmg01", "status": "master", "role": "master" }
],
"mailStats": {
"timeframe": "day",
"countTotal": 100,
"countIn": 60,
"countOut": 40,
"spamIn": 5,
"spamOut": 2,
"virusIn": 1,
"virusOut": 0,
"rblRejects": 2,
"pregreetRejects": 1,
"greylistCount": 7,
"averageProcessTimeMs": 480,
"updatedAt": "2025-10-10T09:30:05Z"
},
"mailCount": [
{
"timestamp": "2025-10-10T09:00:00Z",
"count": 100,
"countIn": 60,
"countOut": 40,
"spamIn": 5,
"spamOut": 2,
"virusIn": 1,
"virusOut": 0,
"rblRejects": 2,
"pregreet": 1,
"greylist": 7,
"index": 0,
"timeframe": "hour"
}
],
"spamDistribution": [
{ "score": "low", "count": 10 }
],
"quarantine": { "spam": 5, "virus": 2 }
}
]
}
```
### Docker Agent Integration
Accept reports from the optional Docker agent to track container workloads outside Proxmox.
```bash
POST /api/agents/docker/report # Submit agent heartbeat payloads (JSON)
DELETE /api/agents/docker/hosts/<id> # Remove a Docker host that has gone offline
GET /api/agent/version # Retrieve the bundled Docker agent version
GET /install-docker-agent.sh # Download the installation convenience script
GET /download/pulse-docker-agent # Download the standalone Docker agent binary
```
Agent routes require authentication. Use an API token or an authenticated session when calling them from automation. When authenticating with tokens, grant `docker:report` for `POST /api/agents/docker/report`, `docker:manage` for Docker host lifecycle endpoints, and `host-agent:report` for host agent submissions. The payload reports restart loops, exit codes, memory pressure, and health probes per container, and Pulse de-duplicates heartbeats per agent ID so you can fan out to multiple Pulse instances safely. Host responses mirror the `/api/state` data, including `issues`, `recentExitCodes`, and `lastSeen` timestamps so external tooling can mimic the built-in Docker workspace.
## Monitoring Data
### Charts Data
Get time-series data for charts (CPU, memory, storage).
```bash
GET /api/charts
GET /api/charts?range=1h # Last hour (default)
GET /api/charts?range=24h # Last 24 hours
GET /api/charts?range=7d # Last 7 days
```
### Storage Information
Get detailed storage information for all nodes.
```bash
GET /api/storage/
GET /api/storage/<node-id>
```
### Storage Charts
Get storage usage trends over time.
```bash
GET /api/storage-charts
```
### Backup Information
Get backup information across all nodes.
```bash
GET /api/backups # All backups
GET /api/backups/unified # Unified view
GET /api/backups/pve # PVE backups only
GET /api/backups/pbs # PBS backups only
```
### Snapshots
Get snapshot information for VMs and containers.
```bash
GET /api/snapshots
```
### Guest Metadata
Manage custom metadata for VMs and containers (e.g., console URLs).
```bash
GET /api/guests/metadata # Get all guest metadata
GET /api/guests/metadata/<guest-id> # Get metadata for specific guest
PUT /api/guests/metadata/<guest-id> # Update guest metadata
DELETE /api/guests/metadata/<guest-id> # Remove guest metadata
```
### Network Discovery
Discover Proxmox nodes on your network.
```bash
GET /api/discover # Get cached discovery results (updates every 5 minutes)
```
Note: Manual subnet scanning via POST is currently not available through the API.
### System Settings
Manage system-wide settings.
```bash
GET /api/system/settings # Get current system settings (includes env overrides)
POST /api/system/settings/update # Update system settings (admin only)
```
## Configuration
### Node Management
Manage Proxmox VE, Proxmox Mail Gateway, and PBS nodes.
```bash
GET /api/config/nodes # List all nodes
POST /api/config/nodes # Add new node
PUT /api/config/nodes/<node-id> # Update node
DELETE /api/config/nodes/<node-id> # Remove node
POST /api/config/nodes/test-connection # Test node connection
POST /api/config/nodes/test-config # Test node configuration (for new nodes)
POST /api/config/nodes/<node-id>/test # Test existing node
```
#### Add Node Example
```bash
curl -X POST http://localhost:7655/api/config/nodes \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"type": "pve",
"name": "My PVE Node",
"host": "https://192.168.1.100:8006",
"user": "monitor@pve",
"password": "password",
"verifySSL": false
}'
```
### System Configuration
Get and update system configuration.
```bash
GET /api/config/system # Get system config
PUT /api/config/system # Update system config
```
### Mock Mode Control
Toggle mock data generation used for demos and development.
```bash
GET /api/system/mock-mode # Report current mock mode status
POST /api/system/mock-mode # Enable/disable mock mode (admin only)
PUT /api/system/mock-mode # Same as POST, but idempotent for tooling
```
These endpoints back the `npm run mock:on|off|status` scripts and trigger the same hot reload behavior. Responses include both `enabled` and the full mock configuration so tooling can preview generated node/guest counts before flipping the switch.
### Security Configuration
#### Security Status
Check current security configuration status.
```bash
GET /api/security/status
```
Returns information about:
- Authentication configuration
- API token status
- Network context (private/public)
- HTTPS status
- Audit logging status
#### Password Management
Manage user passwords.
```bash
POST /api/security/change-password
```
Request body:
```json
{
"currentPassword": "old-password",
"newPassword": "new-secure-password"
}
```
#### Quick Security Setup
Quick setup for authentication (first-time setup).
```bash
POST /api/security/quick-setup
```
Authentication:
- Provide the bootstrap token in the `X-Setup-Token` header (or in the JSON payload) when no auth is configured yet.
- Once credentials exist, an authenticated admin session or API token with `settings:write` is required.
Request body:
```json
{
"username": "admin",
"password": "secure-password",
"apiToken": "raw-token-value",
"setupToken": "<bootstrap-token>"
}
```
The bootstrap token can be read from `/.bootstrap_token` in the data directory (for example `/etc/pulse/.bootstrap_token` on bare metal or `/data/.bootstrap_token` in Docker). The token file is removed automatically after a successful setup run.
#### API Token Management
Manage API tokens for automation workflows, Docker agents, and tool integrations.
Authentication: Requires an admin session or an API token with the scope(s) below:
- `settings:read` for `GET /api/security/tokens`
- `settings:write` for `POST /api/security/tokens` and `DELETE /api/security/tokens/{id}`
**List tokens**
```bash
GET /api/security/tokens
```
Response:
```json
{
"tokens": [
{
"id": "9bf9aa59-3b85-4fd8-9aad-3f19b2c9b6f0",
"name": "ansible",
"prefix": "pulse_1a2b",
"suffix": "c3d4",
"createdAt": "2025-10-14T12:12:34Z",
"lastUsedAt": "2025-10-14T12:21:05Z",
"scopes": ["docker:report", "monitoring:read"]
}
]
}
```
**Create a token**
```bash
POST /api/security/tokens
Content-Type: application/json
{
"name": "ansible",
"scopes": ["monitoring:read"]
}
```
> Omit the `scopes` field to mint a full-access token (`["*"]`). When present, the array must include one or more known scopes—see `docs/CONFIGURATION.md` for the canonical list and descriptions.
Response (token value is returned once):
```json
{
"token": "pulse_1a2b3c4d5e6f7g8h9i0j",
"record": {
"id": "9bf9aa59-3b85-4fd8-9aad-3f19b2c9b6f0",
"name": "ansible",
"prefix": "pulse_1a2b",
"suffix": "c3d4",
"createdAt": "2025-10-14T12:12:34Z",
"lastUsedAt": null,
"scopes": ["monitoring:read"]
}
}
```
**Delete a token**
```bash
DELETE /api/security/tokens/{id}
```
Returns `204 No Content` when the token is revoked.
> Legacy compatibility: `POST /api/security/regenerate-token` is still available but now replaces the entire token list with a single regenerated token. Prefer the endpoints above for multi-token environments.
#### Login
Enhanced login endpoint with lockout feedback.
```bash
POST /api/login
```
Request body:
```json
{
"username": "admin",
"password": "your-password"
}
```
Response includes:
- Remaining attempts after failed login
- Lockout status and duration when locked
- Clear error messages with recovery guidance
#### Logout
End the current session.
```bash
POST /api/logout
```
#### Account Lockout Recovery
Reset account lockouts (requires authentication).
```bash
POST /api/security/reset-lockout
```
Request body:
```json
{
"identifier": "username-or-ip" // Can be username or IP address
}
```
This endpoint allows administrators to manually reset lockouts before the 15-minute automatic expiration.
### Export/Import Configuration
Backup and restore Pulse configuration with encryption.
```bash
POST /api/config/export # Export encrypted config
POST /api/config/import # Import encrypted config
```
**Authentication**: Requires one of:
- Active session (when logged in with password)
- API token via X-API-Token header
- Private network access (automatic for homelab users on 192.168.x.x, 10.x.x.x, 172.16.x.x)
- ALLOW_UNPROTECTED_EXPORT=true (to explicitly allow on public networks)
**Export includes**:
- All nodes and their credentials (encrypted)
- Alert configurations
- Webhook configurations
- Email settings
- System settings (polling intervals, UI preferences)
- Guest metadata (custom console URLs)
**NOT included** (for security):
- Authentication settings (passwords, API tokens)
- Each instance should have its own authentication
## Notifications
### Email Configuration
Manage email notification settings.
```bash
GET /api/notifications/email # Get email config
PUT /api/notifications/email # Update email config (Note: Uses PUT, not POST)
GET /api/notifications/email-providers # List email providers
```
### Test Notifications
Test notification delivery.
```bash
POST /api/notifications/test # Send test notification to all configured channels
```
### Webhook Configuration
Manage webhook notification endpoints.
```bash
GET /api/notifications/webhooks # List all webhooks
POST /api/notifications/webhooks # Create new webhook
PUT /api/notifications/webhooks/<id> # Update webhook
DELETE /api/notifications/webhooks/<id> # Delete webhook
POST /api/notifications/webhooks/test # Test webhook
GET /api/notifications/webhook-templates # Get service templates
GET /api/notifications/webhook-history # Get webhook notification history
```
#### Create Webhook Example
```bash
curl -X POST http://localhost:7655/api/notifications/webhooks \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"name": "Discord Alert",
"url": "https://discord.com/api/webhooks/xxx/yyy",
"method": "POST",
"service": "discord",
"enabled": true
}'
```
#### Custom Payload Template Example
```bash
curl -X POST http://localhost:7655/api/notifications/webhooks \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"name": "Custom Webhook",
"url": "https://my-service.com/webhook",
"method": "POST",
"service": "generic",
"enabled": true,
"template": "{\"alert\": \"{{.Level}}: {{.Message}}\", \"value\": {{.Value}}}"
}'
```
#### Test Webhook
```bash
curl -X POST http://localhost:7655/api/notifications/webhooks/test \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"name": "Test",
"url": "https://example.com/webhook",
"service": "generic"
}'
```
### Notification Queue & Dead Letter Queue (DLQ)
Pulse includes a persistent notification queue with retry logic and a Dead Letter Queue for failed notifications. This ensures notification reliability and provides visibility into delivery failures.
#### Queue Statistics
Get current queue statistics including pending, processing, completed, and failed notification counts.
```bash
GET /api/notifications/queue/stats
```
**Response:**
```json
{
"pending": 3,
"processing": 1,
"completed": 245,
"failed": 2,
"dlq": 2,
"oldestPending": "2024-11-06T12:30:00Z",
"queueDepth": 4
}
```
#### Get Dead Letter Queue
Retrieve notifications that have exhausted all retry attempts. These require manual intervention.
```bash
GET /api/notifications/dlq?limit=100
```
**Query Parameters:**
- `limit` (optional): Maximum number of DLQ items to return (default: 100, max: 1000)
**Response:**
```json
[
{
"id": "email-1699283400000",
"type": "email",
"status": "dlq",
"alerts": [...],
"attempts": 3,
"maxAttempts": 3,
"lastAttempt": "2024-11-06T12:35:00Z",
"lastError": "SMTP connection timeout",
"createdAt": "2024-11-06T12:30:00Z"
}
]
```
#### Retry DLQ Item
Retry a failed notification from the Dead Letter Queue.
```bash
POST /api/notifications/dlq/retry
Content-Type: application/json
{
"id": "email-1699283400000"
}
```
**Response:**
```json
{
"success": true,
"message": "Notification scheduled for retry",
"id": "email-1699283400000"
}
```
#### Delete DLQ Item
Permanently remove a notification from the Dead Letter Queue.
```bash
POST /api/notifications/dlq/delete
Content-Type: application/json
{
"id": "email-1699283400000"
}
```
Or using DELETE method:
```bash
DELETE /api/notifications/dlq/delete
Content-Type: application/json
{
"id": "email-1699283400000"
}
```
**Response:**
```json
{
"success": true,
"message": "DLQ item deleted",
"id": "email-1699283400000"
}
```
**Note:** All notification queue endpoints require admin authentication.
### Alert Management
Comprehensive alert management system.
```bash
# Alert Configuration
GET /api/alerts/ # Get alert configuration and status
POST /api/alerts/ # Update alert settings
# Alert Monitoring
GET /api/alerts/active # Get currently active alerts
GET /api/alerts/history # Get alert history
DELETE /api/alerts/history # Clear alert history
# Alert Actions
POST /api/alerts/<id>/acknowledge # Acknowledge an alert
POST /api/alerts/<id>/clear # Clear a specific alert
POST /api/alerts/<id>/unacknowledge # Remove acknowledgement
```
Alert configuration responses model Pulse's hysteresis thresholds and advanced behaviour:
- `guestDefaults`, `nodeDefaults`, `storageDefault`, `dockerDefaults`, `pmgThresholds` expose the baseline trigger/clear values applied globally. Each metric uses `{ "trigger": 90, "clear": 85 }`, so fractional thresholds (e.g. `12.5`) are supported.
- `overrides` is keyed by resource ID for bespoke thresholds. Setting a threshold to `-1` disables that signal for that resource.
- `timeThresholds` and `metricTimeThresholds` provide per-resource/per-metric grace periods, reducing alert noise on bursty workloads.
- `dockerIgnoredContainerPrefixes` suppresses alerts for ephemeral containers whose name or ID begins with a listed prefix. Matching is case-insensitive and controlled through the Alerts UI.
- `aggregation`, `flapping`, `schedule` configure deduplication, cooldown, and quiet hours. These values are shared with the notification pipeline.
- Active and historical alerts include `metadata.clearThreshold`, `resourceType`, and other context so UIs can render the trigger/clear pair and supply timeline explanations.
### Notification Management
Manage notification destinations and history.
```bash
GET /api/notifications/ # Get notification configuration
POST /api/notifications/ # Update notification settings
GET /api/notifications/history # Get notification history
```
## Auto-Registration
Pulse provides a secure auto-registration system for adding Proxmox nodes using one-time setup codes.
### Generate Setup Code and URL
Generate a one-time setup code and URL for node configuration. This endpoint requires authentication.
```bash
POST /api/setup-script-url
```
Request:
```json
{
"type": "pve", // "pve", "pmg", or "pbs"
"host": "https://192.168.1.100:8006",
"backupPerms": true // Optional: add backup management permissions (PVE only)
}
```
Response:
```json
{
"url": "http://pulse.local:7655/api/setup-script?type=pve&host=...",
"command": "curl -sSL \"http://pulse.local:7655/api/setup-script?...\" | bash",
"setupToken": "4c7f3e8c1c5f4b0da580c4477f4b1c2d",
"tokenHint": "4c7…c2d",
"expires": 1755123456 // Unix timestamp when token expires (5 minutes)
}
```
### Setup Script
Download the setup script for automatic node configuration. This endpoint is public but the script will prompt for a setup code.
```bash
GET /api/setup-script?type=pve&host=<encoded-url>&pulse_url=<encoded-url>
```
The script will:
1. Create a monitoring user (pulse-monitor@pam or pulse-monitor@pbs)
2. Generate an API token for that user
3. Set appropriate permissions
4. Prompt for the setup token (or read `PULSE_SETUP_TOKEN` if set)
5. Auto-register with Pulse if a valid token is provided
### Auto-Register Node
Register a node automatically (used by setup scripts). Requires either a valid setup code or API token.
```bash
POST /api/auto-register
```
Request with setup code (preferred):
```json
{
"type": "pve",
"host": "https://node.local:8006",
"serverName": "node-hostname",
"tokenId": "pulse-monitor@pam!token-name",
"tokenValue": "token-secret-value",
"setupCode": "A7K9P2" // One-time setup code from UI
}
```
Request with API token (legacy):
```bash
curl -X POST http://localhost:7655/api/auto-register \
-H "Content-Type: application/json" \
-H "X-API-Token: your-api-token" \
-d '{
"type": "pve",
"host": "https://node.local:8006",
"serverName": "node-hostname",
"tokenId": "pulse-monitor@pam!token-name",
"tokenValue": "token-secret-value"
}'
```
### Security Management
Additional security endpoints.
```bash
# Apply security settings and restart service
POST /api/security/apply-restart
# Recovery mode (localhost only)
GET /api/security/recovery # Check recovery status
POST /api/security/recovery # Enable/disable recovery mode
Body: {"action": "disable_auth" | "enable_auth"}
```
### Security Features
The setup code system provides multiple layers of security:
- **One-time use**: Each code can only be used once
- **Time-limited**: Codes expire after 5 minutes
- **Hashed storage**: Codes are stored as SHA3-256 hashes
- **Validation**: Codes are validated against node type and host URL
- **No secrets in URLs**: Setup URLs contain no authentication tokens
- **Interactive entry**: Codes are entered interactively, not passed in URLs
### Alternative: Environment Variable
For automation, the setup code can be provided via environment variable:
```bash
PULSE_SETUP_CODE=A7K9P2 curl -sSL "http://pulse:7655/api/setup-script?..." | bash
```
## Guest Metadata
Manage custom metadata for VMs and containers, such as console URLs.
```bash
# Get all guest metadata
GET /api/guests/metadata
# Get metadata for specific guest
GET /api/guests/metadata/<node>/<vmid>
# Update guest metadata
PUT /api/guests/metadata/<node>/<vmid>
POST /api/guests/metadata/<node>/<vmid>
# Delete guest metadata
DELETE /api/guests/metadata/<node>/<vmid>
```
Example metadata update:
```bash
curl -X PUT http://localhost:7655/api/guests/metadata/pve-node/100 \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"consoleUrl": "https://custom-console.example.com/vm/100",
"notes": "Production database server"
}'
```
## System Information
### Current Configuration
Get the current Pulse configuration.
```bash
GET /api/config
```
Returns the complete configuration including nodes, settings, and system parameters.
### Diagnostics
Get comprehensive system diagnostics information.
```bash
GET /api/diagnostics
```
Returns detailed information about:
- System configuration
- Node connectivity status
- Error logs
- Performance metrics
- Service health
> **Caching (v4.24.0+):** Diagnostics results are cached for 45 seconds to protect upstream systems. If the cache is fresh it is returned immediately; otherwise a new probe runs, replacing the cache once complete. Inspect the `X-Diagnostics-Cached-At` header to see when the payload was generated. Probe failures surface in the `errors` array and are tracked by Prometheus metrics (`pulse_diagnostics_*`).
### Network Discovery
Discover Proxmox servers on the network.
```bash
GET /api/discover
```
Response:
```json
{
"servers": [
{
"host": "192.168.1.100",
"port": 8006,
"type": "pve",
"name": "pve-node-1"
}
],
"errors": [],
"scanning": false,
"updated": 1755123456
}
```
### Simple Statistics
Get simplified statistics (lightweight endpoint).
```bash
GET /simple-stats
```
## Session Management
### Logout
End the current user session.
```bash
POST /api/logout
```
## Settings Management
### UI Settings
Manage user interface preferences.
```bash
# Get current UI settings
GET /api/settings
# Update UI settings
POST /api/settings/update
```
Settings include:
- Theme preferences
- Dashboard layout
- Refresh intervals
- Display options
### System Settings
Manage system-wide settings.
```bash
# Get system settings
GET /api/system/settings
# Update system settings
POST /api/system/settings/update
```
System settings include:
- Polling intervals
- Performance tuning
- Feature flags
- Global configurations
## Updates
### Check for Updates
Check if a new version is available. Returns version info, release notes, and deployment-specific instructions.
```bash
GET /api/updates/check
GET /api/updates/check?channel=rc # Override channel (stable/rc)
```
The response includes `deploymentType` so the UI/automation can decide whether a self-service update is possible (`systemd`, `proxmoxve`, `aur`) or if a manual Docker image pull is required.
### Prepare Update Plan
Fetch scripted steps for a target version. Useful when presenting the release picker in the UI.
```bash
GET /api/updates/plan?version=v4.30.0
GET /api/updates/plan?version=v4.30.0&channel=rc
```
Response example (systemd deployment, v4.24.0+):
```json
{
"version": "v4.30.0",
"channel": "stable",
"canAutoUpdate": true,
"requiresRoot": true,
"rollbackSupport": true,
"estimatedTime": "2-3 minutes",
"downloadUrl": "https://github.com/rcourtman/Pulse/releases/download/v4.30.0/pulse-v4.30.0-linux-amd64.tar.gz",
"instructions": "Run the installer script with --version flag",
"prerequisites": ["systemd", "root access"],
"steps": [
"curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash -s -- --version v4.30.0"
]
}
```
### Apply Update
Kick off an update using the download URL returned by the release metadata. Pulse runs the install script asynchronously and streams progress via WebSocket.
```bash
POST /api/updates/apply
Content-Type: application/json
{ "downloadUrl": "https://github.com/rcourtman/Pulse/releases/download/v4.30.0/pulse-v4.30.0-linux-amd64.tar.gz" }
```
Only deployments that can self-update (systemd, Proxmox VE appliance, AUR) will honour this call. Docker users should continue to pull a new image manually.
### Update Status
Retrieve the last known update status or in-flight progress. Possible values: `idle`, `checking`, `downloading`, `installing`, `completed`, `error`.
```bash
GET /api/updates/status
```
### Update History
Pulse captures each self-update attempt in a local history file.
```bash
GET /api/updates/history # List recent update attempts (optional ?limit=&status=)
GET /api/updates/history/entry?id=<uuid> # Inspect a specific update event
```
**Response format (v4.24.0+):**
```json
{
"entries": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"action": "update",
"version": "v4.24.0",
"fromVersion": "v4.23.0",
"channel": "stable",
"status": "completed",
"timestamp": "2025-10-20T10:30:00Z",
"initiated_via": "ui",
"related_event_id": null,
"backup_path": "/opt/pulse/backups/pre-update-v4.23.0.tar.gz",
"duration_seconds": 120,
"error": null
},
{
"id": "650e8400-e29b-41d4-a716-446655440001",
"action": "rollback",
"version": "v4.23.0",
"fromVersion": "v4.24.0",
"channel": "stable",
"status": "completed",
"timestamp": "2025-10-20T11:00:00Z",
"initiated_via": "api",
"related_event_id": "550e8400-e29b-41d4-a716-446655440000",
"backup_path": null,
"duration_seconds": 45,
"error": null
}
]
}
```
Entries include:
- `action`: "update" | "rollback"
- `status`: "pending" | "in_progress" | "completed" | "failed"
- `initiated_via`: How the action was started (ui, api, auto)
- `related_event_id`: Links rollback to original update
- `backup_path`: Location of pre-update backup
- Error details for failed attempts
## Real-time Updates
### WebSocket
Real-time updates are available via WebSocket connection.
```javascript
const ws = new WebSocket('ws://localhost:7655/ws');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Update received:', data);
};
```
The WebSocket broadcasts state updates every few seconds with the complete system state.
### Socket.IO Compatibility
For Socket.IO clients, a compatibility endpoint is available:
```bash
GET /socket.io/
```
### Test Notifications
Test WebSocket notifications:
```bash
POST /api/test-notification
```
## Simple Statistics
Lightweight statistics endpoint for monitoring.
```bash
GET /simple-stats
```
Returns simplified metrics without authentication requirements.
## Prometheus Metrics
Pulse exposes Prometheus-compatible metrics for monitoring the monitoring system itself. These metrics provide observability into alert system health, notification delivery, and queue performance.
### Metrics Endpoint
```bash
GET /metrics
```
**Authentication:** None required (public endpoint)
**Response Format:** Prometheus text exposition format
### Available Metrics
#### Alert Metrics
- **`pulse_alerts_active`** (Gauge) - Number of currently active alerts
- Labels: `level` (info/warning/critical), `type` (cpu/memory/disk/etc)
- **`pulse_alerts_fired_total`** (Counter) - Total number of alerts fired
- Labels: `level`, `type`
- **`pulse_alerts_resolved_total`** (Counter) - Total number of alerts resolved
- Labels: `type`
- **`pulse_alerts_acknowledged_total`** (Counter) - Total number of alerts acknowledged
- **`pulse_alerts_suppressed_total`** (Counter) - Total number of alerts suppressed
- Labels: `reason` (quiet_hours/flapping/rate_limit)
- **`pulse_alert_duration_seconds`** (Histogram) - Duration alerts remain active before resolution
- Labels: `type`
#### Notification Metrics
- **`pulse_notifications_sent_total`** (Counter) - Total notifications sent
- Labels: `method` (email/webhook/apprise), `status` (success/failed)
- **`pulse_notification_queue_depth`** (Gauge) - Number of queued notifications
- Labels: `status` (pending/processing/dlq)
- **`pulse_notification_dlq_total`** (Counter) - Total notifications moved to Dead Letter Queue
- **`pulse_notification_retry_total`** (Counter) - Total notification retry attempts
- **`pulse_notification_duration_seconds`** (Histogram) - Time to deliver notifications
- Labels: `method`
#### Queue Metrics
- **`pulse_queue_depth`** (Gauge) - Current queue depth by status
- Labels: `status`
- **`pulse_queue_items_total`** (Counter) - Total items processed by queue
- Labels: `status` (completed/failed/dlq)
- **`pulse_queue_processing_duration_seconds`** (Histogram) - Time to process queued items
#### System Metrics
- **`pulse_history_save_errors_total`** (Counter) - Total alert history save failures
- **`pulse_history_save_retries_total`** (Counter) - Total history save retry attempts
### Example Prometheus Configuration
```yaml
scrape_configs:
- job_name: 'pulse'
static_configs:
- targets: ['pulse.example.com:7655']
metrics_path: '/metrics'
scrape_interval: 30s
```
### Example PromQL Queries
```promql
# Alert rate per minute
rate(pulse_alerts_fired_total[5m]) * 60
# Notification success rate
rate(pulse_notifications_sent_total{status="success"}[5m]) /
rate(pulse_notifications_sent_total[5m])
# DLQ growth rate
rate(pulse_notification_dlq_total[1h])
# Active alerts by severity
sum by (level) (pulse_alerts_active)
# Average notification delivery time
rate(pulse_notification_duration_seconds_sum[5m]) /
rate(pulse_notification_duration_seconds_count[5m])
```
## Rate Limiting
**v4.24.0:** All responses include rate limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`). 429 responses add `Retry-After`.
**Rate limits by endpoint category:**
- **Authentication**: 10 attempts/minute per IP
- **Config writes**: 30 requests/minute
- **Exports**: 5 requests per 5 minutes
- **Recovery operations**: 3 requests per 10 minutes
- **Update operations**: 20 requests/minute
- **WebSocket connections**: 5 connections/minute per IP
- **General API**: 500 requests/minute per IP
- **Public endpoints**: 1000 requests/minute per IP
**Exempt endpoints** (no rate limits):
- `/api/state` (real-time monitoring)
- `/api/guests/metadata` (frequent polling)
- WebSocket message streaming (after connection established)
**Example response with rate limit headers:**
```
HTTP/1.1 200 OK
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 487
X-RateLimit-Reset: 1754995800
Content-Type: application/json
```
**When rate limited:**
```
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1754995800
Retry-After: 60
Content-Type: application/json
{
"error": "Rate limit exceeded. Please retry after 60 seconds."
}
```
## Error Responses
All endpoints return standard HTTP status codes:
- `200 OK` - Success
- `400 Bad Request` - Invalid request data
- `401 Unauthorized` - Missing or invalid API token
- `404 Not Found` - Resource not found
- `429 Too Many Requests` - Rate limited
- `500 Internal Server Error` - Server error
Error response format:
```json
{
"error": "Error message description"
}
```
## Examples
### Full Example: Monitor a New Node
```bash
# 1. Test connection to node
curl -X POST http://localhost:7655/api/config/nodes/test-connection \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"type": "pve",
"host": "https://192.168.1.100:8006",
"user": "root@pam",
"password": "password"
}'
# 2. Add the node if test succeeds
curl -X POST http://localhost:7655/api/config/nodes \
-H "Content-Type: application/json" \
-H "X-API-Token: your-token" \
-d '{
"type": "pve",
"name": "pve-node-1",
"host": "https://192.168.1.100:8006",
"user": "root@pam",
"password": "password",
"verifySSL": false
}'
# 3. Get monitoring data
curl -H "X-API-Token: your-token" http://localhost:7655/api/state
# 4. Get chart data
curl -H "X-API-Token: your-token" http://localhost:7655/api/charts?range=1h
```
### PowerShell Example
```powershell
# Set variables
$apiUrl = "http://localhost:7655/api"
$apiToken = "your-secure-token"
$headers = @{ "X-API-Token" = $apiToken }
# Check health
$health = Invoke-RestMethod -Uri "$apiUrl/health" -Headers $headers
Write-Host "Status: $($health.status)"
# Get all nodes
$nodes = Invoke-RestMethod -Uri "$apiUrl/config/nodes" -Headers $headers
$nodes | ForEach-Object { Write-Host "Node: $($_.name) - $($_.status)" }
```
### Python Example
```python
import requests
API_URL = "http://localhost:7655/api"
API_TOKEN = "your-secure-token"
headers = {"X-API-Token": API_TOKEN}
# Check health
response = requests.get(f"{API_URL}/health", headers=headers)
health = response.json()
print(f"Status: {health['status']}")
# Get monitoring data
response = requests.get(f"{API_URL}/state", headers=headers)
state = response.json()
for node in state.get("nodes", []):
print(f"Node: {node['name']} - {node['status']}")
```