Référence API¶
Sowel expose une API REST sous /api/v1/ et un endpoint WebSocket à /ws. Tous les endpoints requièrent une authentification, sauf mention contraire. Les réponses sont en JSON.
Base URL : http://<host>:3000
Authentification : passez un token d'accès JWT en header Authorization: Bearer <token>, ou un token d'API en Authorization: Bearer swl_<token>.
Sommaire¶
- Authentication
- Current User (Me)
- Users (Admin)
- Devices
- Equipments
- Zones
- Modes
- Calendar
- Recipes
- Dashboard
- Charts
- Energy
- History
- Integrations (Admin)
- Plugins (Admin)
- Settings (Admin)
- MQTT Brokers
- MQTT Publishers
- Notification Publishers
- Button Actions
- Activité
- Logs (Admin)
- Backup (Admin)
- Health
- WebSocket
Authentication¶
Endpoints publics, aucune auth requise pour status et setup.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/auth/status |
Vérifie si le setup au premier démarrage est requis. Retourne { setupRequired: boolean }. |
POST |
/api/v1/auth/setup |
Crée le premier utilisateur admin (premier démarrage uniquement). Body : { username, password, displayName, language? }. Retourne les tokens JWT. |
POST |
/api/v1/auth/login |
Authentification. Body : { username, password }. Retourne { accessToken, refreshToken }. Limité : 10 req/min. |
POST |
/api/v1/auth/refresh |
Rafraîchit le token d'accès. Body : { refreshToken }. Retourne une nouvelle paire de tokens. |
POST |
/api/v1/auth/logout |
Invalide le refresh token. Body : { refreshToken }. Retourne 204. |
Current User (Me)¶
Profil et tokens de l'utilisateur authentifié.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/me |
Récupère le profil de l'utilisateur courant. |
PUT |
/api/v1/me |
Met à jour le nom d'affichage. Body : { displayName }. |
PUT |
/api/v1/me/preferences |
Met à jour les préférences (langue, thème, etc.). Body : { preferences }. |
PUT |
/api/v1/me/password |
Change le mot de passe. Body : { currentPassword, newPassword }. |
GET |
/api/v1/me/tokens |
Liste les tokens d'API personnels. |
POST |
/api/v1/me/tokens |
Crée un token d'API. Body : { name, expiresAt? }. Retourne la chaîne de token (affichée une fois). |
DELETE |
/api/v1/me/tokens/:id |
Révoque un token d'API. Retourne 204. |
Users (Admin)¶
Toutes les routes de gestion des utilisateurs nécessitent le rôle admin.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/users |
Liste tous les utilisateurs. |
POST |
/api/v1/users |
Crée un utilisateur. Body : { username, password, displayName, role }. |
PUT |
/api/v1/users/:id |
Met à jour un utilisateur. Body : { displayName?, role?, enabled? }. |
DELETE |
/api/v1/users/:id |
Supprime un utilisateur. Impossible de se supprimer ou de supprimer le dernier admin. Retourne 204. |
Devices¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/devices |
Liste tous les devices avec leurs données et ordres courants. |
GET |
/api/v1/devices/:id |
Récupère un device avec données et ordres. |
PUT |
/api/v1/devices/:id |
Met à jour un device. Body : { name?, zoneId? }. |
DELETE |
/api/v1/devices/:id |
Supprime un device. Retourne 204. |
GET |
/api/v1/devices/suggest |
Suggère les devices compatibles avec un type d'équipement. Query : ?type=<equipmentType>. |
GET |
/api/v1/devices/:id/raw |
Récupère les données expose brutes de l'intégration pour un device. |
Equipments¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/equipments |
Liste tous les équipements avec leurs liaisons et données courantes. |
GET |
/api/v1/equipments/:id |
Récupère un équipement avec liaisons et données courantes. |
POST |
/api/v1/equipments |
Crée un équipement. Body : { name, type, zoneId, icon?, description?, deviceIds? }. Si deviceIds est fourni, des liaisons automatiques sont créées. |
PUT |
/api/v1/equipments/:id |
Met à jour un équipement. Body : { name?, type?, zoneId?, icon?, description?, enabled? }. |
DELETE |
/api/v1/equipments/:id |
Supprime un équipement. Retourne 204. |
POST |
/api/v1/equipments/:id/orders/:alias |
Exécute un ordre d'équipement. Body : { value }. |
Data Bindings¶
| Method | Path | Description |
|---|---|---|
POST |
/api/v1/equipments/:id/data-bindings |
Ajoute un DataBinding. Body : { deviceDataId, alias }. |
DELETE |
/api/v1/equipments/:id/data-bindings/:bindingId |
Supprime un DataBinding. Retourne 204. |
Order Bindings¶
| Method | Path | Description |
|---|---|---|
POST |
/api/v1/equipments/:id/order-bindings |
Ajoute un OrderBinding. Body : { deviceOrderId, alias }. |
DELETE |
/api/v1/equipments/:id/order-bindings/:bindingId |
Supprime un OrderBinding. Retourne 204. |
Zones¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/zones |
Liste toutes les zones en arborescence. |
GET |
/api/v1/zones/:id |
Récupère une zone avec ses enfants. |
POST |
/api/v1/zones |
Crée une zone. Body : { name, parentId?, icon?, description?, displayOrder? }. |
PUT |
/api/v1/zones/:id |
Met à jour une zone. Body : { name?, parentId?, icon?, description?, displayOrder? }. |
DELETE |
/api/v1/zones/:id |
Supprime une zone. Retourne 204. |
PUT |
/api/v1/zones/reorder |
Réordonne des zones de même niveau. Body : { parentId, orderedIds }. Retourne 204. |
GET |
/api/v1/zones/aggregation |
Récupère les données agrégées de toutes les zones (température, mouvement, lightsOn, etc.). |
POST |
/api/v1/zones/:id/orders/:orderKey |
Exécute un ordre au niveau zone (par ex. allLightsOff, allShuttersClose). Body : { value? }. |
Modes¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/modes |
Liste tous les modes avec détails. |
GET |
/api/v1/modes/:id |
Récupère un mode avec impacts et état. |
POST |
/api/v1/modes |
Crée un mode. Body : { name, icon?, description? }. |
PUT |
/api/v1/modes/:id |
Met à jour un mode. Body : { name?, icon?, description? }. |
DELETE |
/api/v1/modes/:id |
Supprime un mode. Retourne 204. |
POST |
/api/v1/modes/:id/activate |
Active le mode. |
POST |
/api/v1/modes/:id/deactivate |
Désactive le mode. |
POST |
/api/v1/modes/:id/apply-to-zone/:zoneId |
Applique les impacts du mode à une zone spécifique. |
Zone Mode Impacts¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/zones/:zoneId/mode-impacts |
Récupère les impacts de mode d'une zone. |
PUT |
/api/v1/modes/:id/impacts/:zoneId |
Définit les actions d'impact de zone. Body : { actions: ZoneModeImpactAction[] }. |
DELETE |
/api/v1/modes/:id/impacts/:zoneId |
Supprime un impact de zone. Retourne 204. |
Mode Triggers¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/modes/:id/triggers |
Récupère les liaisons de bouton qui déclenchent ce mode. |
Calendar¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/calendar/profiles |
Liste tous les profils de calendrier. |
GET |
/api/v1/calendar/active |
Récupère le profil actif et ses créneaux. |
PUT |
/api/v1/calendar/active |
Définit le profil actif. Body : { profileId }. |
GET |
/api/v1/calendar/profiles/:id/slots |
Liste les créneaux d'un profil. |
POST |
/api/v1/calendar/profiles/:id/slots |
Ajoute un créneau. Body : { days, time, modeActions }. |
PUT |
/api/v1/calendar/slots/:slotId |
Met à jour un créneau. Body : { days?, time?, modeActions? }. |
DELETE |
/api/v1/calendar/slots/:slotId |
Supprime un créneau. Retourne 204. |
Recipes¶
Recipe Definitions¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/recipes |
Liste les définitions de recettes disponibles (modèles). |
GET |
/api/v1/recipes/:recipeId |
Récupère une définition de recette avec slots et i18n. |
Recipe Instances¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/recipe-instances |
Liste toutes les instances de recettes actives. |
POST |
/api/v1/recipe-instances |
Crée une instance. Body : { recipeId, params }. |
PUT |
/api/v1/recipe-instances/:id |
Met à jour les params de l'instance. Body : { params }. |
DELETE |
/api/v1/recipe-instances/:id |
Arrête et supprime l'instance. Retourne 204. |
POST |
/api/v1/recipe-instances/:id/enable |
Active une instance désactivée. |
POST |
/api/v1/recipe-instances/:id/disable |
Désactive (met en pause) une instance en cours. |
POST |
/api/v1/recipe-instances/:id/actions |
Envoie une action à une recette en cours. Body : { action, payload? }. |
GET |
/api/v1/recipe-instances/:id/log |
Récupère le journal d'exécution. Query : ?limit=50. |
Dashboard¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/dashboard/widgets |
Liste tous les widgets du tableau de bord, ordonnés par display order. |
POST |
/api/v1/dashboard/widgets |
Crée un widget (admin). Body : { type, equipmentId?, zoneId?, family?, label?, icon? }. |
PATCH |
/api/v1/dashboard/widgets/:id |
Met à jour le label, l'icône ou la config d'un widget (admin). Body : { label?, icon?, config? }. |
DELETE |
/api/v1/dashboard/widgets/:id |
Supprime un widget (admin). Retourne 204. |
PUT |
/api/v1/dashboard/widgets/order |
Réordonne les widgets (admin). Body : { order: string[] }. |
Charts¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/charts |
Liste les configurations de graphiques sauvegardées. |
GET |
/api/v1/charts/:id |
Récupère une configuration de graphique. |
POST |
/api/v1/charts |
Crée un graphique. Body : { name, config }. |
PUT |
/api/v1/charts/:id |
Met à jour un graphique. Body : { name?, config? }. |
DELETE |
/api/v1/charts/:id |
Supprime un graphique. Retourne 204. |
Energy¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/energy/status |
Statut du module énergie (disponibilité, sources, tarif configuré). |
GET |
/api/v1/energy/history |
Interroge l'historique d'énergie. Query : ?period=day&date=2026-01-15. Périodes : day, week, month, year. Retourne la ventilation HP/HC et les données de production. |
GET |
/api/v1/energy/by-usage |
Séries temporelles de consommation par sous-compteur pour les mêmes buckets de période que /energy/history. Query : ?period=day&date=2026-01-15. Retourne une série par sous-compteur energy_meter plus un résidu other (max(0, total - Σ submeters)) et les totaux par équipement. |
GET |
/api/v1/settings/energy/tariff |
Récupère la configuration tarifaire (grilles HP/HC et prix). |
PUT |
/api/v1/settings/energy/tariff |
Met à jour la configuration tarifaire. Body : { schedules, prices }. |
History¶
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/history/status |
Statut du module historique (connexion, nombre de bindings historisés, stats). |
GET |
/api/v1/history/retention |
Statut de rétention et de downsampling pour tous les buckets/tâches InfluxDB. |
GET |
/api/v1/history/bindings/:equipmentId |
Liste les réglages d'historisation des data bindings d'un équipement. |
PUT |
/api/v1/history/bindings/:equipmentId/:bindingId |
Définit le flag d'historisation. Body : { historize } (null, 0 ou 1). |
GET |
/api/v1/history/sparkline/zone/:zoneId/:category |
Données de sparkline 24 h au niveau zone (par ex. tendance de température). |
GET |
/api/v1/history/sparkline/:equipmentId/:alias |
Données de sparkline 24 h au niveau équipement. |
GET |
/api/v1/history/:equipmentId |
Liste les alias historisés pour un équipement. |
GET |
/api/v1/history/:equipmentId/:alias |
Interroge les données de série temporelle. Query : ?from=-24h&to=&aggregation=auto. Agrégations : raw, 1h, 1d, auto. |
Integrations (Admin)¶
Routes admin uniquement pour gérer les plugins d'intégration de devices.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/integrations |
Liste toutes les intégrations avec statut, réglages et nombre de devices. |
POST |
/api/v1/integrations/:id/start |
Démarre une intégration. |
POST |
/api/v1/integrations/:id/stop |
Arrête une intégration. |
POST |
/api/v1/integrations/:id/restart |
Redémarre une intégration (stop + start). |
POST |
/api/v1/integrations/:id/refresh |
Force un refresh des données (intégrations en polling uniquement). |
Plugins (Admin)¶
Routes admin uniquement pour la gestion des plugins tiers.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/plugins |
Liste les plugins installés. |
GET |
/api/v1/plugins/store |
Liste les plugins disponibles depuis le registre. |
POST |
/api/v1/plugins/install |
Installe depuis GitHub. Body : { repo } (par ex. "owner/repo"). |
POST |
/api/v1/plugins/:id/uninstall |
Désinstalle un plugin. |
POST |
/api/v1/plugins/:id/enable |
Active un plugin (le charge et le démarre). |
POST |
/api/v1/plugins/:id/disable |
Désactive un plugin (le stoppe et le décharge). |
Settings (Admin)¶
Stockage clé-valeur des réglages admin (utilisé pour les configs d'intégration, les réglages maison, etc.).
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/settings |
Récupère tous les réglages. |
PUT |
/api/v1/settings |
Met à jour les réglages. Body : objet clé-valeur { "key": "value", ... }. |
MQTT Brokers¶
Brokers MQTT externes pour la publication sortante.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/mqtt-brokers |
Liste tous les brokers MQTT. |
POST |
/api/v1/mqtt-brokers |
Crée un broker. Body : { name, url, username?, password? }. |
PUT |
/api/v1/mqtt-brokers/:id |
Met à jour un broker. Body : { name?, url?, username?, password? }. |
DELETE |
/api/v1/mqtt-brokers/:id |
Supprime un broker. Retourne 204. |
MQTT Publishers¶
Publishers MQTT sortants qui poussent les données Sowel vers des brokers externes. Chaque publisher cible un seul topic MQTT et peut avoir plusieurs mappings de données (sources équipement, zone, ou recette). Quand onChangeOnly est activé, le publisher ne publie que lorsqu'une valeur change réellement, utile pour ne pas inonder les afficheurs externes de heartbeats périodiques.
Chaque mapping porte son propre flag enabled (par défaut true). Les mappings désactivés sont ignorés en publication live, dans le snapshot initial et dans le bouton manuel "Test", de sorte qu'une source saisonnière peut être mise en sourdine sans perdre son câblage source/clé. Le flag enabled au niveau du publisher l'emporte toujours : si le publisher est éteint, tous ses mappings le sont aussi, indépendamment de leur flag par mapping.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/mqtt-publishers |
Liste tous les publishers avec leurs mappings. |
GET |
/api/v1/mqtt-publishers/:id |
Récupère un publisher avec ses mappings. |
POST |
/api/v1/mqtt-publishers |
Crée un publisher. Body : { name, brokerId, topic, enabled?, onChangeOnly? }. |
PUT |
/api/v1/mqtt-publishers/:id |
Met à jour un publisher. Body : { name?, brokerId?, topic?, enabled?, onChangeOnly? }. |
DELETE |
/api/v1/mqtt-publishers/:id |
Supprime un publisher. Retourne 204. |
POST |
/api/v1/mqtt-publishers/:id/test |
Test : publie un snapshot. |
POST |
/api/v1/mqtt-publishers/:id/mappings |
Ajoute un mapping de données. Body : { publishKey, sourceType, sourceId, sourceKey, enabled? }. enabled par défaut à true si omis. |
PUT |
/api/v1/mqtt-publishers/:id/mappings/:mappingId |
Met à jour un mapping. Accepte { publishKey?, sourceType?, sourceId?, sourceKey?, enabled? }. Le flag enabled bascule la publication on/off sans supprimer le mapping. |
DELETE |
/api/v1/mqtt-publishers/:id/mappings/:mappingId |
Supprime un mapping. Retourne 204. |
Notification Publishers¶
Notifications push (actuellement Telegram) déclenchées par des changements de données.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/notification-publishers |
Liste tous les notification publishers avec leurs mappings. |
GET |
/api/v1/notification-publishers/:id |
Récupère un publisher avec ses mappings. |
POST |
/api/v1/notification-publishers |
Crée un publisher. Body : { name, channelType, channelConfig, enabled? }. |
PUT |
/api/v1/notification-publishers/:id |
Met à jour un publisher. |
DELETE |
/api/v1/notification-publishers/:id |
Supprime un publisher. Retourne 204. |
POST |
/api/v1/notification-publishers/:id/test-channel |
Teste le canal de notification (envoie un message de test). |
POST |
/api/v1/notification-publishers/:id/test |
Teste le publisher complet (déclenche les mappings). |
POST |
/api/v1/notification-publishers/:id/mappings |
Ajoute un mapping de déclenchement. Body : { message, sourceType, sourceId, sourceKey, throttleMs? }. |
PUT |
/api/v1/notification-publishers/:id/mappings/:mappingId |
Met à jour un mapping. |
DELETE |
/api/v1/notification-publishers/:id/mappings/:mappingId |
Supprime un mapping. Retourne 204. |
Button Actions¶
Mappe les appuis sur des boutons physiques (boutons Zigbee, etc.) à des actions (activation de mode, ordres d'équipement, basculement de recette).
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/equipments/:id/action-bindings |
Liste les action bindings d'un équipement bouton. |
POST |
/api/v1/equipments/:id/action-bindings |
Crée une liaison. Body : { actionValue, effectType, config }. Types d'effet : mode_activate, mode_toggle, equipment_order, recipe_toggle. |
PUT |
/api/v1/equipments/:id/action-bindings/:bindingId |
Met à jour une liaison. |
DELETE |
/api/v1/equipments/:id/action-bindings/:bindingId |
Supprime une liaison. Retourne 204. |
Activité¶
Événements moteur récents pour le panneau d'activité de la vue Zone. Lit depuis le ring buffer en mémoire (rétention 24 h, plafonné à 2000 entrées, remis à zéro au redémarrage). Voir Zones — Fil d'activité pour la description côté utilisateur.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/activity |
Liste les items d'activité. Query : ?zoneId=<uuid>&includeDescendants=true&limit=100. limit est borné à [1, 200], défaut 100. |
Filtrage : les items dont le zoneId correspond au paramètre de query sont retournés, plus les items dont le zoneId vaut null (événements globaux : changements de mode, lever/coucher de soleil, alarmes système). Quand includeDescendants=true (défaut), les items des zones enfants sont aussi retournés.
Format de réponse :
{
"items": [
{
"id": "uuid",
"timestamp": 1715864400000,
"category": "order",
"zoneId": "uuid-du-salon",
"message": {
"template": "order.executed",
"params": { "equipmentName": "Lumière", "alias": "state", "value": "ON" }
},
"source": { "kind": "recipe", "instanceId": "...", "recipeName": "Motion Light" }
}
]
}
Catégories : order, motion, recipe, mode, sunlight, alarm.
Sources : recipe, mode, manual, button, external. Le champ source n'est présent que sur les items category=order.
Logs (Admin)¶
Accès aux logs admin uniquement depuis le ring buffer en mémoire.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/logs |
Interroge les logs. Query : ?limit=100&level=error&module=mqtt&search=text&since=ISO. Retourne les entrées, la capacité, le niveau courant et les modules disponibles. |
GET |
/api/v1/logs/level |
Récupère le niveau de log runtime courant. |
PUT |
/api/v1/logs/level |
Change le niveau de log runtime. Body : { level }. Valides : debug, info, warn, error, fatal, silent. |
Backup (Admin)¶
Backup et restauration complète de la configuration, admin uniquement.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/backup |
Exporte la configuration complète. Retourne un ZIP (JSON SQLite + CSV InfluxDB) ou JSON s'il n'y a pas de données InfluxDB. |
POST |
/api/v1/backup |
Restaure la configuration depuis un backup JSON. Body : payload de backup avec { version: 1, tables }. |
Health¶
Aucune authentification requise.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/health |
Vérification de santé du système. Retourne le statut, l'uptime, les statuts d'intégration, le nombre de devices et la version du moteur. |
WebSocket¶
Endpoint : ws://<host>:3000/ws?token=<jwt_or_api_token>
L'authentification est passée via le paramètre de query token. Les tokens JWT et les tokens d'API (préfixe swl_) sont tous deux acceptés.
Connexion¶
À la connexion, le serveur envoie un message de bienvenue :
Les clients sont automatiquement abonnés au topic system.
S'abonner aux topics¶
Envoyez un message JSON pour vous abonner à des topics supplémentaires :
Topics disponibles : devices, equipments, zones, modes, recipes, calendar, mqtt-publishers, system, logs, activity.
Le topic system est toujours inclus, indépendamment de l'abonnement.
Livraison des événements¶
Les événements sont batchés toutes les 200 ms et envoyés sous forme de tableau JSON. Les événements de données à haute fréquence sont dédupliqués par batch, seule la dernière valeur par device/équipement/clé de zone est envoyée.
[
{ "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 }
]
Flux d'activité¶
Quand on est abonné au topic activity, le serveur pousse chaque nouvel item au fil de l'eau. Chaque envoi est un événement unitaire (non batché), avec le même format que les items retournés par GET /api/v1/activity :
{
"type": "activity.added",
"item": {
"id": "uuid",
"timestamp": 1715864400000,
"category": "motion",
"zoneId": "uuid-de-zone",
"message": { "template": "motion.detected", "params": { "equipmentName": "PIR Salon" } }
}
}
Les clients doivent filtrer le flux live par leur scope de zone courant (le serveur diffuse tous les items aux abonnés, sans filtrage par client).
Streaming de logs¶
Quand on est abonné au topic logs, les entrées de log sont streamées individuellement (non batchées) :