Skip to content

API Reference

Pankha Fan Control exposes a REST API for configuration and a WebSocket interface for real-time data. Base URL: http://<server-ip>:3143

Two kinds of identifiers appear in these routes:

  • Database IDs (numeric): :id for systems, and :sensorId / :fanId in label, visibility, and ordering routes.
  • Hardware IDs (string, e.g. it8628_fan_1): :fanId in the fan speed and calibration routes. IPMI agents use the zone ID here (e.g. cpu_zone).

MethodEndpointDescription
GET/healthBackend health check with service statistics
GET/api/overviewAggregate stats across all systems
GET/api/websocket/infoWebSocket connection info and stats
POST/api/emergency-stopForce all fans to 100% on all systems

MethodEndpointDescription
GET/api/systemsList all registered agents
POST/api/systemsAdd new system
GET/api/systems/limitGet agent limit info (current count, tier limit)
GET/api/systems/:idGet system details with sensors/fans
PUT/api/systems/:idUpdate system configuration
DELETE/api/systems/:idRemove system
GET/api/systems/:id/statusReal-time connection status
GET/api/systems/:id/diagnosticsGet hardware diagnostics from agent
MethodEndpointDescription
GET/api/systems/controller/statusFan profile controller status
PUT/api/systems/controller/intervalSet controller update interval
MethodEndpointDescription
GET/api/systems/:id/sensorsGet all sensors for system
PUT/api/systems/:id/sensors/:sensorId/labelSet custom sensor label
PUT/api/systems/:id/sensors/:sensorId/visibilityShow/hide sensor ({ is_hidden })
GET/api/systems/:id/sensor-visibilityGet visibility settings
PUT/api/systems/:id/sensor-groups/:groupName/visibilityShow/hide sensor group
GET/api/systems/:id/sensor-orderGet custom sensor display order
PUT/api/systems/:id/sensors/orderReorder sensors within a group
PUT/api/systems/:id/sensor-groups/orderReorder sensor groups
MethodEndpointDescription
GET/api/systems/:id/fansGet all fans for system
PUT/api/systems/:id/fans/:fanIdSet fan speed ({ speed: 0-100 })
PUT/api/systems/:id/fans/:fanId/labelSet custom fan label
PUT/api/systems/:id/fans/:fanId/visibilityShow/hide fan ({ is_hidden })

Manual speed commands return 409 while the fan is locked by a running calibration.

MethodEndpointDescription
GET/api/systems/:id/calibrationsCalibration snapshot for all fans on a system
GET/api/systems/:id/fans/:fanId/calibrationCurrent calibration facts for one fan
GET/api/systems/:id/fans/:fanId/calibration/historyPast calibration runs (trend data)
POST/api/systems/:id/fans/:fanId/calibrateStart a manual calibration run (409 if offline)
POST/api/systems/:id/fans/:fanId/stalls/clearClear the fan’s unexpected-stop log

See Calibration & Health for what these measurements mean.

MethodEndpointDescription
PUT/api/systems/:id/update-intervalSet agent polling interval (seconds)
PUT/api/systems/:id/fan-stepSet fan speed step % (smoothing)
PUT/api/systems/:id/hysteresisSet temperature hysteresis (°C)
PUT/api/systems/:id/emergency-tempSet emergency temperature threshold
PUT/api/systems/:id/failsafe-speedSet failsafe fan speed (0-100%)
PUT/api/systems/:id/enable-fan-controlEnable/disable fan control
PUT/api/systems/:id/log-levelSet agent log level
PUT/api/systems/:id/nameSet agent display name
POST/api/systems/:id/updateTrigger remote agent self-update
MethodEndpointDescription
GET/api/systems/settingsGet all backend settings
GET/api/systems/settings/:keyGet a specific setting by key
PUT/api/systems/settings/:keyUpdate a setting ({ "value": "..." })

Allowed setting keys: controller_update_interval, graph_history_hours, data_retention_days, accent_color, hover_tint_color, hardware_prune_days, fan_recalibration_days, ui_font_primary, ui_font_secondary, ui_font_scale, hub_log_level

MethodEndpointDescription
PUT/api/systems/:id/profileAssign profile to system
POST/api/systems/:id/profilesCreate system-specific profile
GET/api/systems/:id/historyHistorical data (start_time, end_time, sensor_ids, fan_ids, limit)
GET/api/systems/:id/chartsGet aggregated chart data

MethodEndpointDescription
GET/api/fan-profilesList all profiles
GET/api/fan-profiles/:idGet profile details
POST/api/fan-profilesCreate new profile
PUT/api/fan-profiles/:idUpdate profile
DELETE/api/fan-profiles/:idDelete profile
GET/api/fan-profiles/statsProfile statistics
POST/api/fan-profiles/assignAssign profile to fan
GET/api/fan-profiles/assignments/:systemIdGet fan assignments
POST/api/fan-profiles/calculate-speedCalculate speed for temp
GET/api/fan-profiles/exportExport profiles to JSON
POST/api/fan-profiles/importImport profiles from JSON
GET/api/fan-profiles/defaultsList available default profiles
POST/api/fan-profiles/load-defaultsLoad default profiles into database

User-defined categories for organizing profiles (built-in types like silent and performance are system types and cannot be changed).

MethodEndpointDescription
GET/api/fan-profile-typesList all types with is_system flag and use count
POST/api/fan-profile-typesCreate a type ({ name }, 409 on name collision)
PATCH/api/fan-profile-types/:nameRename a user-defined type
DELETE/api/fan-profile-types/:nameDelete an unused user-defined type

MethodEndpointDescription
GET/api/fan-configurations/:systemIdGet fan configurations
POST/api/fan-configurations/sensorConfigure fan sensor mapping

Combine real sensors into a computed one (see Dashboard for the feature itself). A virtual sensor is referenced by other APIs as __virtual__<id>.

MethodEndpointDescription
GET/api/virtual-sensors/:systemIdList virtual sensors for a system
GET/api/virtual-sensors/:id/usageWhere this virtual sensor is used (fan assignments)
POST/api/virtual-sensorsCreate ({ system_id, name, operation: max|avg|median, sensor_ids }, minimum 2 sensors)
PUT/api/virtual-sensors/orderReorder virtual sensors
PUT/api/virtual-sensors/:idUpdate name, operation, or members
DELETE/api/virtual-sensors/:idDelete a virtual sensor

MethodEndpointDescription
POST/api/discovery/scanScan network for agents
GET/api/discovery/hardwareGet discovered hardware
POST/api/discovery/test-fanTest fan control
GET/api/discovery/systems/:id/sensors/scanScan for new sensors
PUT/api/discovery/systems/:id/sensors/:sensorIdUpdate discovered sensor
POST/api/discovery/systems/:id/sensor-mappingMap sensors to labels

MethodEndpointDescription
POST/api/deploy/templatesGenerate a deployment token (expires in 24h)
GET/api/deploy/linuxServe dynamic Linux install script (?token=<token>)
GET/api/deploy/ipmiServe dynamic IPMI install script (?token=<token>)
GET/api/deploy/hub/statusStatus of locally cached agent binaries
POST/api/deploy/hub/stageDownload a specific agent version to the hub
DELETE/api/deploy/hub/clearClear all locally cached agent binaries
GET/api/deploy/binaries/:agentType/:archServe cached binary (os_linux/ipmi_host, x86_64/aarch64)
GET/api/deploy/binaries/:archServe cached OS agent binary (legacy form)

Vendor profiles that teach the IPMI agent how to talk to a server’s BMC.

MethodEndpointDescription
GET/api/deploy/profilesVendor/model catalog for profile selection
GET/api/deploy/profiles/refreshRe-scan profile files on disk
GET/api/deploy/profiles/assigned/:agentIdResolved profile assigned to an agent
PUT/api/deploy/profiles/assign/:agentIdAssign a profile to an agent
POST/api/deploy/profiles/customSave a custom profile from the Profile Builder
GET/api/deploy/profiles/:vendor/:modelGet one profile definition
MethodEndpointDescription
POST/api/systems/:id/execute-raw-ipmiRun a raw IPMI command on an agent (profile testing)

MethodEndpointDescription
GET/api/config/deploymentGet deployment config (hub IP and port)

MethodEndpointDescription
GET/api/licenseGet current license info (tier, limits, expiration)
POST/api/licenseActivate license key
DELETE/api/licenseRemove license (revert to free tier)
GET/api/license/pricingGet tier pricing info
POST/api/license/syncForce sync with license server (check for renewals)

Endpoint: ws://<server-ip>:3143/websocket

MessageDescription
subscribeSubscribe to topics (e.g. systems:all)
unsubscribeUnsubscribe from topics
requestFullSyncRequest a complete state snapshot
getSystemDataRequest one system’s current data
getOverviewRequest aggregate stats
pingKeep-alive check
EventDescription
fullStateComplete snapshot (on connect / full sync)
systemDeltaIncremental updates (only changed values)
systemOfflineAgent disconnected
agentRegisteredAgent connected
agentUnregisteredAgent stopped gracefully
agentErrorAgent reported a hardware error
agentRecoveredAgent recovered from an error state
agentConfigUpdatedConfig change (immediate broadcast)
fanCalibrationStatusCalibration run lifecycle (running/done/failed)
fanStalledStall watchdog: fan read 0 RPM while commanded to spin
fanStallClearedStall condition cleared
commandCompletedA dispatched agent command finished
commandFailedA dispatched agent command failed
licenseUpdatedLicense changed on the backend (refetch /api/license)
{
"type": "systemDelta",
"data": {
"agentId": "linux-agent-1",
"timestamp": "2025-01-01T12:00:00Z",
"changes": ["sensors", "fans"],
"sensors": [{ "id": "temp1", "temperature": 45.2 }],
"fans": [{ "id": "fan1", "rpm": 1200, "speed": 40 }]
}
}

Terminal window
curl -X PUT http://localhost:3143/api/systems/1/fans/it8628_fan_1 \
-H "Content-Type: application/json" \
-d '{"speed": 75}'
Terminal window
curl -X POST http://localhost:3143/api/virtual-sensors \
-H "Content-Type: application/json" \
-d '{
"system_id": 1,
"name": "CPU + NVMe Max",
"operation": "max",
"sensor_ids": [12, 15, 18]
}'
Terminal window
curl -X POST http://localhost:3143/api/systems/1/fans/it8628_fan_1/calibrate
Terminal window
curl http://localhost:3143/health

{
"success": false,
"error": "Error message",
"message": "Detailed description"
}
CodeMeaning
200Success
201Created
400Bad request
403Forbidden (license limit / read-only mode)
404Not found
409Conflict (system offline, calibration lock, name collision)
500Server error
503Service unavailable

  • URL Parameters: Replace :id, :fanId, etc. with actual values (see the identifier note at the top of this page).