API Reference
Sowel exposes a REST API under /api/v1/ and a WebSocket endpoint at /ws. All endpoints require authentication unless noted otherwise. Responses use JSON.
Base URL : http://<host>:3000
Authentication : Pass a JWT access token as Authorization: Bearer <token> header, or an API token as Authorization: Bearer swl_<token>.
Table of Contents
Authentication
Public endpoints -- no auth required for status and setup.
Method
Path
Description
GET
/api/v1/auth/status
Check if first-run setup is required. Returns { setupRequired: boolean }.
POST
/api/v1/auth/setup
Create the first admin user (first-run only). Body: { username, password, displayName, language? }. Returns JWT tokens.
POST
/api/v1/auth/login
Authenticate. Body: { username, password }. Returns { accessToken, refreshToken }. Rate limited: 10 req/min.
POST
/api/v1/auth/refresh
Refresh access token. Body: { refreshToken }. Returns new token pair.
POST
/api/v1/auth/logout
Invalidate refresh token. Body: { refreshToken }. Returns 204.
Current User (Me)
Authenticated user's own profile and tokens.
Method
Path
Description
GET
/api/v1/me
Get current user profile.
PUT
/api/v1/me
Update display name. Body: { displayName }.
PUT
/api/v1/me/preferences
Update preferences (language, theme, etc.). Body: { preferences }.
PUT
/api/v1/me/password
Change password. Body: { currentPassword, newPassword }.
GET
/api/v1/me/tokens
List own API tokens.
POST
/api/v1/me/tokens
Create API token. Body: { name, expiresAt? }. Returns token string (shown only once).
DELETE
/api/v1/me/tokens/:id
Revoke an API token. Returns 204.
Users (Admin)
All user management routes require admin role.
Method
Path
Description
GET
/api/v1/users
List all users.
POST
/api/v1/users
Create user. Body: { username, password, displayName, role }.
PUT
/api/v1/users/:id
Update user. Body: { displayName?, role?, enabled? }.
DELETE
/api/v1/users/:id
Delete user. Cannot delete self or last admin. Returns 204.
Devices
Method
Path
Description
GET
/api/v1/devices
List all devices with current data and orders.
GET
/api/v1/devices/:id
Get device with data and orders.
PUT
/api/v1/devices/:id
Update device. Body: { name?, zoneId? }.
DELETE
/api/v1/devices/:id
Remove device. Returns 204.
GET
/api/v1/devices/suggest
Suggest compatible devices for an equipment type. Query: ?type=<equipmentType>.
GET
/api/v1/devices/:id/raw
Get raw integration expose data for a device.
Equipments
Method
Path
Description
GET
/api/v1/equipments
List all equipments with bindings and current data.
GET
/api/v1/equipments/:id
Get equipment with bindings and current data.
POST
/api/v1/equipments
Create equipment. Body: { name, type, zoneId, icon?, description?, deviceIds? }. If deviceIds provided, auto-bindings are created.
PUT
/api/v1/equipments/:id
Update equipment. Body: { name?, type?, zoneId?, icon?, description?, enabled? }.
DELETE
/api/v1/equipments/:id
Delete equipment. Returns 204.
POST
/api/v1/equipments/:id/orders/:alias
Execute an equipment order. Body: { value }.
Data Bindings
Method
Path
Description
POST
/api/v1/equipments/:id/data-bindings
Add a DataBinding. Body: { deviceDataId, alias }.
DELETE
/api/v1/equipments/:id/data-bindings/:bindingId
Remove a DataBinding. Returns 204.
Order Bindings
Method
Path
Description
POST
/api/v1/equipments/:id/order-bindings
Add an OrderBinding. Body: { deviceOrderId, alias }.
DELETE
/api/v1/equipments/:id/order-bindings/:bindingId
Remove an OrderBinding. Returns 204.
Zones
Method
Path
Description
GET
/api/v1/zones
List all zones as a tree structure.
GET
/api/v1/zones/:id
Get zone with children.
POST
/api/v1/zones
Create zone. Body: { name, parentId?, icon?, description?, displayOrder? }.
PUT
/api/v1/zones/:id
Update zone. Body: { name?, parentId?, icon?, description?, displayOrder? }.
DELETE
/api/v1/zones/:id
Delete zone. Returns 204.
PUT
/api/v1/zones/reorder
Reorder sibling zones. Body: { parentId, orderedIds }. Returns 204.
GET
/api/v1/zones/aggregation
Get aggregated data for all zones (temperature, motion, lightsOn, etc.).
POST
/api/v1/zones/:id/orders/:orderKey
Execute zone-level order (e.g. allLightsOff, allShuttersClose). Body: { value? }.
Modes
Method
Path
Description
GET
/api/v1/modes
List all modes with details.
GET
/api/v1/modes/:id
Get mode with impacts and state.
POST
/api/v1/modes
Create mode. Body: { name, icon?, description? }.
PUT
/api/v1/modes/:id
Update mode. Body: { name?, icon?, description? }.
DELETE
/api/v1/modes/:id
Delete mode. Returns 204.
POST
/api/v1/modes/:id/activate
Activate mode.
POST
/api/v1/modes/:id/deactivate
Deactivate mode.
POST
/api/v1/modes/:id/apply-to-zone/:zoneId
Apply mode impacts to a specific zone.
Zone Mode Impacts
Method
Path
Description
GET
/api/v1/zones/:zoneId/mode-impacts
Get mode impacts for a zone.
PUT
/api/v1/modes/:id/impacts/:zoneId
Set zone impact actions. Body: { actions: ZoneModeImpactAction[] }.
DELETE
/api/v1/modes/:id/impacts/:zoneId
Remove zone impact. Returns 204.
Mode Triggers
Method
Path
Description
GET
/api/v1/modes/:id/triggers
Get button bindings that trigger this mode.
Calendar
Method
Path
Description
GET
/api/v1/calendar/profiles
List all calendar profiles.
GET
/api/v1/calendar/active
Get the active profile with its slots.
PUT
/api/v1/calendar/active
Set the active profile. Body: { profileId }.
GET
/api/v1/calendar/profiles/:id/slots
List slots for a profile.
POST
/api/v1/calendar/profiles/:id/slots
Add a slot. Body: { days, time, modeActions }.
PUT
/api/v1/calendar/slots/:slotId
Update a slot. Body: { days?, time?, modeActions? }.
DELETE
/api/v1/calendar/slots/:slotId
Delete a slot. Returns 204.
Recipes
Recipe Definitions
Method
Path
Description
GET
/api/v1/recipes
List available recipe definitions (templates).
GET
/api/v1/recipes/:recipeId
Get recipe definition with slots and i18n.
Recipe Instances
Method
Path
Description
GET
/api/v1/recipe-instances
List all active recipe instances.
POST
/api/v1/recipe-instances
Create instance. Body: { recipeId, params }.
PUT
/api/v1/recipe-instances/:id
Update instance params. Body: { params }.
DELETE
/api/v1/recipe-instances/:id
Stop and delete instance. Returns 204.
POST
/api/v1/recipe-instances/:id/enable
Enable a disabled instance.
POST
/api/v1/recipe-instances/:id/disable
Disable (pause) a running instance.
POST
/api/v1/recipe-instances/:id/actions
Send an action to a running recipe. Body: { action, payload? }.
GET
/api/v1/recipe-instances/:id/log
Get execution log. Query: ?limit=50.
Dashboard
Method
Path
Description
GET
/api/v1/dashboard/widgets
List all dashboard widgets ordered by display order.
POST
/api/v1/dashboard/widgets
Create widget (admin). Body: { type, equipmentId?, zoneId?, family?, label?, icon? }.
PATCH
/api/v1/dashboard/widgets/:id
Update widget label, icon, or config (admin). Body: { label?, icon?, config? }.
DELETE
/api/v1/dashboard/widgets/:id
Delete widget (admin). Returns 204.
PUT
/api/v1/dashboard/widgets/order
Reorder widgets (admin). Body: { order: string[] }.
Charts
Method
Path
Description
GET
/api/v1/charts
List saved chart configurations.
GET
/api/v1/charts/:id
Get a chart configuration.
POST
/api/v1/charts
Create chart. Body: { name, config }.
PUT
/api/v1/charts/:id
Update chart. Body: { name?, config? }.
DELETE
/api/v1/charts/:id
Delete chart. Returns 204.
Energy
Method
Path
Description
GET
/api/v1/energy/status
Energy module status (available, sources, tariff configured).
GET
/api/v1/energy/history
Query energy history. Query: ?period=day&date=2026-01-15. Periods: day, week, month, year. Returns HP/HC breakdown and production data.
GET
/api/v1/settings/energy/tariff
Get tariff configuration (HP/HC schedules and prices).
PUT
/api/v1/settings/energy/tariff
Update tariff configuration. Body: { schedules, prices }.
History
Method
Path
Description
GET
/api/v1/history/status
History module status (connected, historized bindings count, stats).
GET
/api/v1/history/retention
Retention and downsampling status for all InfluxDB buckets/tasks.
GET
/api/v1/history/bindings/:equipmentId
List historize settings for an equipment's data bindings.
PUT
/api/v1/history/bindings/:equipmentId/:bindingId
Set historize flag. Body: { historize } (null, 0, or 1).
GET
/api/v1/history/sparkline/zone/:zoneId/:category
Zone-level 24h sparkline data (e.g. temperature trend).
GET
/api/v1/history/sparkline/:equipmentId/:alias
Equipment-level 24h sparkline data.
GET
/api/v1/history/:equipmentId
List historized aliases for an equipment.
GET
/api/v1/history/:equipmentId/:alias
Query time-series data. Query: ?from=-24h&to=&aggregation=auto. Aggregations: raw, 1h, 1d, auto.
Integrations (Admin)
Admin-only routes for managing device integration plugins.
Method
Path
Description
GET
/api/v1/integrations
List all integrations with status, settings, and device counts.
POST
/api/v1/integrations/:id/start
Start an integration.
POST
/api/v1/integrations/:id/stop
Stop an integration.
POST
/api/v1/integrations/:id/restart
Restart an integration (stop + start).
POST
/api/v1/integrations/:id/refresh
Force a data refresh (polling integrations only).
Plugins (Admin)
Admin-only routes for third-party plugin management.
Method
Path
Description
GET
/api/v1/plugins
List installed plugins.
GET
/api/v1/plugins/store
List available plugins from the registry.
POST
/api/v1/plugins/install
Install from GitHub. Body: { repo } (e.g. "owner/repo").
POST
/api/v1/plugins/:id/uninstall
Uninstall a plugin.
POST
/api/v1/plugins/:id/enable
Enable a plugin (loads and starts it).
POST
/api/v1/plugins/:id/disable
Disable a plugin (stops and unloads it).
Settings (Admin)
Admin-only key-value settings store (used for integration config, home settings, etc.).
Method
Path
Description
GET
/api/v1/settings
Get all settings.
PUT
/api/v1/settings
Update settings. Body: key-value object { "key": "value", ... }.
MQTT Brokers
External MQTT brokers for outbound publishing.
Method
Path
Description
GET
/api/v1/mqtt-brokers
List all MQTT brokers.
POST
/api/v1/mqtt-brokers
Create broker. Body: { name, url, username?, password? }.
PUT
/api/v1/mqtt-brokers/:id
Update broker. Body: { name?, url?, username?, password? }.
DELETE
/api/v1/mqtt-brokers/:id
Delete broker. Returns 204.
MQTT Publishers
Outbound MQTT publishers that push Sowel data to external brokers.
Method
Path
Description
GET
/api/v1/mqtt-publishers
List all publishers with mappings.
GET
/api/v1/mqtt-publishers/:id
Get publisher with mappings.
POST
/api/v1/mqtt-publishers
Create publisher. Body: { name, brokerId, topic, enabled? }.
PUT
/api/v1/mqtt-publishers/:id
Update publisher.
DELETE
/api/v1/mqtt-publishers/:id
Delete publisher. Returns 204.
POST
/api/v1/mqtt-publishers/:id/test
Test publish a snapshot.
POST
/api/v1/mqtt-publishers/:id/mappings
Add data mapping. Body: { publishKey, sourceType, sourceId, sourceKey }.
PUT
/api/v1/mqtt-publishers/:id/mappings/:mappingId
Update mapping.
DELETE
/api/v1/mqtt-publishers/:id/mappings/:mappingId
Delete mapping. Returns 204.
Notification Publishers
Push notifications (currently Telegram) triggered by data changes.
Method
Path
Description
GET
/api/v1/notification-publishers
List all notification publishers with mappings.
GET
/api/v1/notification-publishers/:id
Get publisher with mappings.
POST
/api/v1/notification-publishers
Create publisher. Body: { name, channelType, channelConfig, enabled? }.
PUT
/api/v1/notification-publishers/:id
Update publisher.
DELETE
/api/v1/notification-publishers/:id
Delete publisher. Returns 204.
POST
/api/v1/notification-publishers/:id/test-channel
Test the notification channel (sends a test message).
POST
/api/v1/notification-publishers/:id/test
Test the full publisher (trigger mappings).
POST
/api/v1/notification-publishers/:id/mappings
Add trigger mapping. Body: { message, sourceType, sourceId, sourceKey, throttleMs? }.
PUT
/api/v1/notification-publishers/:id/mappings/:mappingId
Update mapping.
DELETE
/api/v1/notification-publishers/:id/mappings/:mappingId
Delete mapping. Returns 204.
Map physical button presses (Zigbee buttons, etc.) to actions (mode activation, equipment orders, recipe toggles).
Method
Path
Description
GET
/api/v1/equipments/:id/action-bindings
List action bindings for a button equipment.
POST
/api/v1/equipments/:id/action-bindings
Create binding. Body: { actionValue, effectType, config }. Effect types: mode_activate, mode_toggle, equipment_order, recipe_toggle.
PUT
/api/v1/equipments/:id/action-bindings/:bindingId
Update binding.
DELETE
/api/v1/equipments/:id/action-bindings/:bindingId
Delete binding. Returns 204.
Logs (Admin)
Admin-only log access from the in-memory ring buffer.
Method
Path
Description
GET
/api/v1/logs
Query logs. Query: ?limit=100&level=error&module=mqtt&search=text&since=ISO. Returns entries, capacity, current level, and available modules.
GET
/api/v1/logs/level
Get current runtime log level.
PUT
/api/v1/logs/level
Change runtime log level. Body: { level }. Valid: debug, info, warn, error, fatal, silent.
Backup (Admin)
Admin-only full configuration backup and restore.
Method
Path
Description
GET
/api/v1/backup
Export full configuration. Returns ZIP (SQLite JSON + InfluxDB CSVs) or JSON if no InfluxDB data.
POST
/api/v1/backup
Restore configuration from JSON backup. Body: backup payload with { version: 1, tables }.
Health
No authentication required.
Method
Path
Description
GET
/api/v1/health
System health check. Returns status, uptime, integration statuses, device counts, and engine version.
WebSocket
Endpoint : ws://<host>:3000/ws?token=<jwt_or_api_token>
Authentication is passed via the token query parameter. Both JWT access tokens and API tokens (swl_ prefix) are accepted.
Connection
On connection, the server sends a welcome message:
{ "type" : "connected" , "message" : "Connected to Sowel engine" , "version" : "0.1.0" }
Clients are automatically subscribed to the system topic.
Subscribing to Topics
Send a JSON message to subscribe to additional topics:
{ "type" : "subscribe" , "topics" : [ "devices" , "equipments" , "zones" , "modes" , "recipes" ] }
Available topics : devices, equipments, zones, modes, recipes, calendar, mqtt-publishers, system, logs.
The system topic is always included regardless of subscription.
Event Delivery
Events are batched every 200ms and sent as a JSON array. High-frequency data events are deduplicated per batch -- only the latest value per device/equipment/zone key is sent.
[
{ "type" : "device.data.updated" , "deviceId" : "..." , "key" : "temperature" , "value" : 22.5 },
{ "type" : "equipment.data.changed" , "equipmentId" : "..." , "alias" : "state" , "value" : "ON" },
{ "type" : "zone.data.changed" , "zoneId" : "..." , "key" : "temperature" , "value" : 21.8 }
]
Log Streaming
When subscribed to the logs topic, log entries are streamed individually (not batched):
{
"type" : "log.entry" ,
"level" : "info" ,
"module" : "devices" ,
"msg" : "Device discovered" ,
"time" : 1700000000
}