Diese Routen verwalten Geräte und Geräteprofile per Code. Die Pfade liegen unter https://<your host>/tenant/<tenantId>. Konventionen (Paginierung, strikte Bodies, Zeiten) stehen in REST API basics.
Geräte
| Methode | Pfad | Berechtigung | Funktion |
|---|---|---|---|
| GET | /api/iot/devices | iot_device.devices.read | Geräte auflisten |
| POST | /api/iot/devices | iot_device.devices.create | Gerät und dessen Zugriffstoken anlegen |
| GET | /api/iot/devices/{deviceId} | iot_device.devices.read | Ein Gerät abrufen |
| PATCH | /api/iot/devices/{deviceId} | iot_device.devices.update | Name, Bezeichnung, Typ, Profil, Status, Zusatzinformationen ändern |
| DELETE | /api/iot/devices/{deviceId} | iot_device.devices.delete | Gerät löschen |
| GET | /api/iot/devices/{deviceId}/connection | iot_device.devices.read | Wo sich das Gerät verbindet |
| GET | /api/iot/devices/{deviceId}/connections | iot_device.devices.read | Das Verbindungsprotokoll |
| GET | /api/iot/devices/{deviceId}/log | iot_device.devices.read | Verbindungsprotokoll und Audit-Einträge, zusammengeführt |
Geräte auflisten
GET /api/iot/devices (Seiten ab 1)
| Parameter | Werte |
|---|---|
page | ab 1 (Standard 1) |
pageSize | 1 bis 100 (Standard 20) |
search | bis zu 128 Zeichen: Name, Bezeichnung oder Seriennummer |
deviceProfileId | eine Profil-ID |
status | ACTIVE, QUARANTINED oder DISABLED |
isGateway | true oder false |
online | true, false oder unknown |
sort | name, connection, lastSeen, createdAt, mit :asc oder :desc |
{
"devices": [
{
"deviceId": "6f1c…",
"name": "pump-station-04",
"label": "Pump station 4",
"type": "pump-controller",
"serial": null,
"deviceProfileId": "a1b2…",
"status": "ACTIVE",
"isGateway": false,
"gatewayDeviceId": null,
"model": null,
"fwTitle": null,
"fwVersion": null,
"online": true,
"active": true,
"lastConnectAt": "2026-11-08T06:12:03.000Z",
"lastDisconnectAt": null,
"lastActivityAt": "2026-11-09T09:41:10.000Z",
"lastRemoteIp": "203.0.113.20",
"lastTransport": "mqtts",
"additionalInfo": {},
"createdAt": "2026-10-01T08:00:00.000Z",
"updatedAt": "2026-11-08T06:12:03.000Z"
}
],
"total": 1
}
online ist null bei einem Profil, dessen Online-Regel Nur zuletzt gesehen ist. GET /api/iot/devices/{deviceId} antwortet mit { "device": {...} } mit denselben Feldern plus profileName und profileTransport.
Gerät anlegen
POST/tenant/{tenantId}/api/iot/devices
Felder: name (Pflicht, 1 bis 128 Zeichen, eindeutig), label (bis 255), type (bis 64), deviceProfileId (sonst das Standardprofil), isGateway, additionalInfo (ein Objekt mit bis zu 50 Schlüsseln und 8 KiB). Die Antwort enthält das Gerät und bei Profilen, deren Geräte sich selbst anmelden, ein Zugriffstoken in credential.secret.token. Das Token wird nur in dieser Antwort angezeigt.
Request-Body application/json
{
"name": "pump-station-04",
"label": "Pump station 4",
"deviceProfileId": "a1b2…"
}
Beispiel curl
curl -X POST 'https://<your-host>/tenant/{tenantId}/api/iot/devices' \
-H 'Content-Type: application/json' \
-d '{"name":"pump-station-04","label":"Pump station 4","deviceProfileId":"a1b2…"}'
Antworten
201Erstellt
{
"device": {
"deviceId": "6f1c…",
"name": "pump-station-04",
"status": "ACTIVE",
"…": "…"
},
"credential": {
"credential": {
"credentialId": "…",
"type": "ACCESS_TOKEN",
"…": "…"
},
"secret": {
"token": "Xq3…"
}
}
}
403Verboten
{
"message": "The device limit of this account is reached.",
"code": "FORBIDDEN",
"details": {
"key": "max_devices",
"limit": 43,
"current": 43,
"adding": 1
}
}
409Konflikt
{
"message": "A device with this name already exists.",
"code": "CONFLICT",
"details": {
"reason": "name_taken"
}
}
Gerät ändern
PATCH /api/iot/devices/{deviceId} akzeptiert beliebige der Felder name, label, type, deviceProfileId, isGateway, additionalInfo, status (ACTIVE oder DISABLED). Nur geänderte Werte senden. Ein unter Quarantäne stehendes Gerät wird über die Bereitstellung freigegeben, nicht hier: „Ein unter Quarantäne stehendes Gerät wird über die Bereitstellung aktiviert, nicht hier bearbeitet.“ Ein neuer Name, ein neues Profil oder das Deaktivieren beendet die aktive Sitzung des Geräts; es verbindet sich mit den neuen Einstellungen erneut.
Gerät löschen
DELETE antwortet mit { "message": "Device deleted." }. Die Messwerte des Geräts werden im Hintergrund entfernt. Ein Gerät, das noch verwendet wird, wird mit 409 abgelehnt, zum Beispiel: „The device is still in use by 1 asset placement or relation (iot_asset).“ Entfernen Sie es zuvor von seinem Asset und löschen Sie seine Relationen: siehe Placing devices und Relations.
Verbindungsdetails
GET /api/iot/devices/{deviceId}/connection gibt nichts Geheimes zurück:
{
"connection": {
"mqtt": { "host": "mqtt.example.com", "port": 8883, "tls": true },
"httpBase": "https://acme.example.com",
"topics": { "telemetry": "v1/telemetry", "attributes": "v1/attributes", "rpcRequest": "v1/rpc/req/+", "rpcResponse": "v1/rpc/res/{id}" },
"telemetryKeys": [{ "key": "temperature", "type": "number" }]
}
}
mqtt ist null, wenn das Profil MQTT an diesem Listener ablehnt; rpcRequest und rpcResponse sind null beim Schema Legacy compatible.
Protokolle
GET .../connections?page=1&pageSize=50: Verbindungsaufbau und -abbau, neueste zuerst (Seiten ab 1,pageSizebis 100).GET .../log?page=1&pageSize=50&source=connection|audit: das Verbindungsprotokoll und die Audit-Einträge des Geräts, zusammengeführt, neueste zuerst.page×pageSizedarf höchstens 1.000 ergeben.
Gerätezugangsdaten
| Methode | Pfad | Funktion |
|---|---|---|
| GET | /api/iot/devices/{deviceId}/credentials | Die aktiven Zugangsdaten, ohne deren Geheimnis |
| PUT | /api/iot/devices/{deviceId}/credentials | Auf andere Zugangsdaten wechseln |
| POST | /api/iot/devices/{deviceId}/credentials/rotate | Ein neues Geheimnis desselben Typs (201) |
| DELETE | /api/iot/devices/{deviceId}/credentials | Zugangsdaten widerrufen |
Alle benötigen iot_device.credentials.manage. Wechsel, Rotation und Widerruf beenden die alten Zugangsdaten sofort (es gibt kein Übergangsfenster) und trennen das Gerät.
PUT-Bodies:
{ "type": "ACCESS_TOKEN" }
{ "type": "MQTT_BASIC", "username": "pump04", "clientId": "pump04", "password": null }
{ "type": "X509_CERTIFICATE", "certificateId": "…" }
Bei MQTT_BASIC lassen Sie password weg (oder setzen null), um ein generiertes Passwort zu erhalten. Ein gewähltes Passwort braucht mindestens 16 Zeichen, Vielfalt und darf den Benutzernamen oder die Client-ID nicht enthalten. Der Benutzername provision ist reserviert. Die Antwort ist { "credential": {...}, "secret": { "token": "…" } } oder { ..., "secret": { "password": "…" } }, nur einmal angezeigt; ein X.509-Zertifikat hat kein Geheimnis. Ein X.509-Zugang wird rotiert, indem ein neues Zertifikat angehängt wird: „Ein X.509-Zugang wird durch Anhängen eines neuen Zertifikats rotiert.“ Siehe Device credentials.
Geräteprofile
| Methode | Pfad | Berechtigung | Funktion |
|---|---|---|---|
| GET | /api/iot/device-profiles | iot_device_profile.profiles.read | Auflisten (page ab 1, pageSize, search, transportType, onlineRule, sort) |
| POST | /api/iot/device-profiles | iot_device_profile.profiles.write | Anlegen |
| GET | /api/iot/device-profiles/{profileId} | .profiles.read | Lesen |
| PATCH | /api/iot/device-profiles/{profileId} | .profiles.write | Ändern; expectedVersion senden |
| DELETE | /api/iot/device-profiles/{profileId} | .profiles.write | Löschen |
| POST | /api/iot/device-profiles/{profileId}/default | .profiles.write | Als Standard festlegen |
| POST | /api/iot/device-profiles/{profileId}/duplicate | .profiles.write | Kopieren als „ |
| GET | /api/iot/device-profiles/{profileId}/key-usage?keys=a,b | .profiles.read | Wer liest diese Schlüssel (Regeln, Boards, Flows) |
| GET, PUT, POST | /api/iot/device-profiles/{profileId}/provisioning | iot_device_profile.provisioning.manage | Bereitstellungseinstellungen; POST rotiert oder widerruft einen Bereitstellungsschlüssel |
Sortierfelder: name, transport, online, updated. Eine Liste antwortet mit { "profiles": [...], "total": n }; ein Profil mit { "profile": {...} }.
Ein Profil anlegen
Ein neues Profil braucht einen name (bis 128 Zeichen) und eine onlineRule: LIVE_SOCKET (Live-Verbindung), UPLINK_WINDOW (Letzte Nachricht, braucht zusätzlich expectedIntervalS, 60 bis 604.800) oder LAST_SEEN_ONLY (Nur zuletzt gesehen). Jedes andere Feld erhält seinen Standardwert.
{
"name": "Cold room sensor",
"onlineRule": "UPLINK_WINDOW",
"expectedIntervalS": 300,
"transportType": "MQTT",
"telemetrySchema": [
{ "key": "temperature", "type": "number", "unit": "°C", "label": "Temperature", "min": -30, "max": 10, "decimals": 1 }
]
}
Ausgewählte Felder und ihre Bereiche:
| Feld | Bereich |
|---|---|
transportType | MQTT, HTTP, ANY oder ein registriertes Protokoll |
allowedAuthModes | 1 bis 3 aus ACCESS_TOKEN, MQTT_BASIC, X509_CERTIFICATE |
mqttTransport | TLS_REQUIRED (Standard) oder PLAINTEXT_ALLOWED |
allowedNetworks | bis zu 64 Netze oder Adressen |
payloadMaxBytes | 1.024 bis 65.536 |
downlinkMaxBytes | 1.024 bis 65.536 |
inactivityTimeoutSec | 10 bis 604.800 |
maxGatewayChildren | 0 bis 10.000 |
rpcTimeoutDefaultSec | 1 bis 300 |
onlineWindowFactor | 1,5 bis 10, eine Nachkommastelle |
telemetrySchema, cfgSchema | jeweils bis zu 500 Schlüssel |
rateLimits | count:seconds[,count:seconds] pro Familie, zum Beispiel "telemetry_msgs": "10:1,300:60" |
Lesen Sie zuerst ein bestehendes Profil, um jedes Feld mit seinem aktuellen Wert zu sehen; der Profil-Editor deckt dieselben Felder mit Erläuterungen ab, siehe Geräteprofile.
Ablehnungen
Ein Body, der eine Feldregel verletzt, ergibt ein 400 mit den Problemen in issues, jeweils mit path und message, zum Beispiel online_rule_required (ein neues Profil benötigt eine Online-Regel), expected_interval_required (Letzte Nachricht benötigt expectedIntervalS) oder online_rule_not_allowed (die Online-Regel passt nicht zum Transport).
Andere Ablehnungen enthalten details.reason, zum Beispiel:
| Grund | Bedeutung |
|---|---|
stale_profile | Jemand hat das Profil gespeichert, seit Sie es gelesen haben (409) |
name_taken | Ein anderes Profil hat diesen Namen |
default_profile | Das Standardprofil kann nicht gelöscht werden |
builtin_profile | Ein eingebautes Profil kann auf diesem Weg nicht geändert werden |
still_referenced | Geräte oder andere Datensätze verwenden das Profil noch |
reference_unverifiable | Ein Modul, das das Profil verwenden könnte, konnte nicht abgefragt werden; versuchen Sie es erneut |

