API HTTP
L'API HTTP convient aux appareils qui ne peuvent pas maintenir une connexion ouverte, aux réseaux qui n'autorisent que du HTTPS ordinaire et à la mise en route du firmware : contrairement à MQTT, chaque requête répond en vous indiquant ce que la plateforme a fait de chacun des relevés que vous avez envoyés.
URL de base
https://api.sensocan.com/api/v1
Authentification
Chaque requête transporte le jeton d'accès (access token) de l'appareil sous forme de jeton Bearer :
Authorization: Bearer {DEVICE_ACCESS_TOKEN}
Obtenez le jeton depuis Détails de l'appareil → Afficher le jeton. Le jeton appartient à un seul appareil, et l'URL à laquelle vous envoyez vos relevés doit porter l'UUID de ce même appareil.

L'action de régénération, dans la même boîte de dialogue, émet un nouveau jeton et invalide l'ancien dans le même geste. Chaque appareil qui utilise l'ancien jeton commence à recevoir des 401 tant que vous n'y avez pas flashé le nouveau.
En-têtes
| En-tête | Valeur | Obligatoire |
|---|---|---|
Authorization | Bearer {DEVICE_ACCESS_TOKEN} | Oui |
Content-Type | application/json | Oui |
Accept | application/json | Recommandé — sans lui, la réponse de limite de requêtes revient en HTML et non en JSON |
Points de terminaison (endpoints)
1. Un relevé pour un capteur
POST /devices/{device_uuid}/sensors/{sensor}/readings
{sensor} est soit le slug du capteur (son identifiant court), soit son UUID : les deux figurent sur la page du capteur.
{
"data": {
"value": 25.5,
"timestamp": "2026-09-03T10:00:00Z"
},
"battery_voltage": 3.7
}
| Champ | Type | Obligatoire | Notes |
|---|---|---|---|
data | objet | Oui | Exactement un relevé. Pour en envoyer plusieurs, le point de terminaison par lot |
data.value | nombre | Oui | Les valeurs non numériques sont rejetées |
data.timestamp | chaîne ISO 8601 | Non | Par défaut, l'heure d'arrivée de la requête |
battery_voltage | nombre (volts), de 0 à 100 | Non | Se place à côté de data, pas à l'intérieur |
Toute autre clé placée dans data est conservée en métadonnées avec le relevé : voir les règles de charge utile communes.
2. Plusieurs relevés pour un capteur
POST /devices/{device_uuid}/sensors/{sensor}/readings/bulk
{
"data": [
{ "value": 22.1, "timestamp": "2026-09-03T09:00:00Z" },
{ "value": 22.4, "timestamp": "2026-09-03T09:15:00Z" },
{ "value": 22.8, "timestamp": "2026-09-03T09:30:00Z" }
],
"battery_voltage": 3.6
}
data doit être un tableau comportant au moins une entrée. Chaque entrée suit les mêmes règles que data ci-dessus.
3. Des relevés pour plusieurs capteurs
POST /devices/{device_uuid}/readings
{
"data": [
{
"sensor_slug": "temp_01",
"value": 25.5,
"timestamp": "2026-09-03T10:00:00Z"
},
{ "sensor_uuid": "7a8b9c0d-1234-5678-90ab-cdef12345678", "value": 60.2 },
{ "sensor_slug": "door_01", "value": 1 }
],
"battery_voltage": 3.7
}
Chaque entrée désigne son propre capteur avec sensor_slug ou sensor_uuid ; l'un des deux est obligatoire. Utilisez ce point de terminaison pour un appareil qui porte plusieurs capteurs : trois requêtes distinctes font trois fois le même travail.
Ce que la réponse vous apprend
Une requête qui a fait passer au moins un relevé répond 202 Accepted :
{
"message": "Readings accepted and queued for rule chain processing.",
"accepted": 3,
"duplicates": 0,
"rejected": {},
"sensor": "temp_01"
}
| Champ | Signification |
|---|---|
accepted | Les relevés remis à la chaîne de règles |
duplicates | Les relevés reconnus comme la répétition d'un envoi antérieur. Comptés comme un succès : rejouer un tampon est sans risque |
rejected | Les motifs d'écartement rencontrés, avec leur nombre. Vide ({}) quand rien n'a été écarté |
sensor | L'identifiant que vous avez mis dans l'URL, renvoyé tel quel. Seulement sur les deux points de terminaison à capteur unique |
Un succès partiel reste un 202 : cinq relevés envoyés, trois acceptés et deux rejetés, vous valent un 202 accompagné du détail. Lisez les nombres, et ne prenez pas le code de statut à lui seul pour la preuve que tout est arrivé.
Un relevé accepté est remis à la chaîne de règles qui s'applique à ce capteur, et c'est cette chaîne qui décide de son sort, y compris de son enregistrement. Une chaîne dépourvue d'étape d'enregistrement produit exactement cela : des réponses 202 impeccables et aucune donnée nulle part dans l'interface. Chaque compte démarre avec une Chaîne de règles par défaut qui enregistre ; si vous avez construit la vôtre, vérifiez-la dans Gestion → Chaînes de règles.
Les motifs de rejet
Les clés qui peuvent apparaître dans rejected :
| Clé | Ce que cela signifie | Comment y remédier |
|---|---|---|
dropped_unknown_sensor | L'identifiant ne correspondait à aucun capteur de cet appareil | Comparez-le au slug et à l'UUID affichés sur la page du capteur. La correspondance est exacte et sensible à la casse |
dropped_missing_identifier | Une entrée du lot n'avait ni sensor_slug ni sensor_uuid | Donnez l'un des deux à chaque entrée |
dropped_missing_value | Un relevé n'avait pas de value | Envoyez value sur chaque relevé ; pour un échantillon raté, n'envoyez pas null, omettez-le |
dropped_invalid_shape | La structure de data ne correspondait pas au point de terminaison | Envoyez un objet au point de terminaison unitaire et un tableau aux deux autres |
dropped_future_timestamp | Un horodatage restait en avance sur l'heure du serveur après correction d'horloge | Envoyez un horodatage ISO 8601, ou omettez-le et laissez l'heure d'arrivée faire foi |
dropped_duplicate | La même valeur pour le même capteur est revenue dans la fenêtre de suppression des doublons | Rien à corriger. Signalé dans duplicates, jamais dans rejected |
Erreurs
| Code | Corps | Cause et remède |
|---|---|---|
401 | {"message":"Device authentication token required.","error":"missing_token"} | Pas d'en-tête Authorization, ou pas sous la forme Bearer … |
401 | {"message":"Invalid device authentication token.","error":"invalid_token"} | Le jeton n'appartient pas à l'appareil désigné dans l'URL, ou il a été régénéré |
404 | {"message":"Device not found.","error":"device_not_found"} | Le {device_uuid} de l'URL ne désigne aucun appareil. Recopiez-le depuis Détails de l'appareil |
404 | {"message":"No reading matched a sensor on this device.","error":"sensor_not_found","sensors":["temp_01"]} | Rien dans la charge utile (payload) ne visait un capteur réel. sensors liste les identifiants restés sans correspondance |
422 | {"message":"Validation failed.","errors":{"data.value":["The sensor value is required."]}} | Le corps de la requête est mal formé. errors nomme le champ fautif |
422 | {"message":"No readings were accepted.","error":"no_readings_accepted","rejected":{"dropped_missing_value":2}} | Le corps était valide mais tous les relevés ont été écartés. rejected en dit la raison |
429 | {"message":"Too Many Attempts."} | Limite de requêtes atteinte. Temporisez, puis réessayez : voir ci-dessous |
Les échecs de validation courants derrière un 422 Validation failed : data absent ou vide, value absent ou non numérique, timestamp qui n'est pas une date analysable, une entrée de lot sans sensor_slug ni sensor_uuid, battery_voltage hors de la plage de 0 à 100.
Limitation des requêtes
La limite est de 1000 requêtes par minute. Elle se compte par adresse source : plusieurs appareils derrière une même connexion internet se partagent donc le budget.
| En-tête | Présent sur | Signification |
|---|---|---|
X-RateLimit-Limit | Toute réponse | Le plafond — 1000 |
X-RateLimit-Remaining | Toute réponse | Requêtes restantes dans la fenêtre en cours |
Retry-After | 429 seulement | Secondes à attendre avant de réessayer |
X-RateLimit-Reset | 429 seulement | Le moment où la fenêtre se réinitialise |
Respectez Retry-After au lieu de réessayer aussitôt, et temporisez de façon exponentielle si vous continuez à buter dessus. Si un appareil s'approche de la limite, regroupez ses capteurs dans une seule requête plutôt que d'envoyer une requête par capteur.
Exemple complet
curl -X POST \
https://api.sensocan.com/api/v1/devices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/readings \
-H "Authorization: Bearer your-device-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"data": [
{ "sensor_slug": "temp_01", "value": 25.5 },
{ "sensor_slug": "humidity_01", "value": 60.2 }
],
"battery_voltage": 3.7
}'
{
"message": "Readings accepted and queued for rule chain processing.",
"accepted": 2,
"duplicates": 0,
"rejected": {}
}
Traiter les réponses dans le firmware
202— videz votre tampon de tout ce qui est compté dansacceptedetduplicates. Un relevé passé dansrejectedne réussira pas davantage à la reprise : consignez-le plutôt que de le renvoyer indéfiniment.401et404— c'est de la configuration, pas un incident passager. Cessez de réessayer et remontez le problème là où un opérateur le verra.422— un problème de firmware. Consignez le corps de la réponse : il nomme le champ en cause.429— attendez le nombre de secondes indiqué parRetry-After, puis réessayez.5xxou pas de réponse — c'est passager. Temporisez de façon exponentielle et gardez les relevés en tampon ; les horodatages rendent le rattrapage exact, et une horloge en avance ne vous coûte rien.
Dépannage
Des réponses 202 mais aucune donnée nulle part. Ouvrez la page Détails de l'appareil. Le tableau des capteurs affiche pour chaque capteur sa Valeur actuelle et sa Dernière mise à jour.

Si Dernière connexion se met à jour alors que chaque capteur indique « Aucune donnée », c'est que la chaîne de règles ne les enregistre pas : vérifiez Gestion → Chaînes de règles. Si certains capteurs se mettent à jour et d'autres non, les identifiants des capteurs muets ne correspondent à aucun capteur de cet appareil, et le corps du 404 comme les compteurs de rejected vous le disaient déjà.
Tout renvoie 401. Vérifiez que le jeton n'a pas été régénéré et que l'UUID d'appareil présent dans l'URL est bien celui auquel ce jeton appartient. Un jeton qui fonctionne pour un appareil est rejeté sur un autre.
Les relevés mis en tampon reviennent en doublons. C'est la réponse attendue à un rejeu. Considérez-les comme transmis et faites avancer votre tampon.