> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Siemens Industrial Edge Management

> Client-mode REST API connector for Siemens Industrial Edge Management (IEM): log in with an IEM user, list Edge Devices with their status and statistics, browse the app catalog and app configs, deploy or start, stop, update and reconfigure apps on devices, and follow the batch and install jobs

Technical Preview

## Overview

One client-mode connector, **SiemensIEM**, for the Portal Public API of a self-hosted Siemens Industrial Edge Management (IEM-OS, or IEM Pro on Kubernetes). IEM is the central place where you onboard Industrial Edge Devices (IEDs) and deploy Industrial Edge apps to them. With this connector the broker can publish your edge fleet into the Unified Namespace (device status, statistics, installed apps) and drive app rollouts from MQTT: deploy an app, restart or stop it, push a new app configuration, then follow the batch until every device job is `COMPLETED`.

The connector talks to the IEM management API only. Data on the devices themselves (Databus MQTT, connectors, IIH) is not part of this connector.

| Event | Topic | Request | Notes |
| - | - | - | - |
| Login | `mes/siemens-iem/token/create` | `POST /portal/api/v1/login/direct` | Username/password (or technical user) -> data.access\_token, valid 24 h |
| VerifyToken | `mes/siemens-iem/token/verify` | `GET /portal/api/v1/auth-tokens/verify` | Returns the auth details of the token |
| Logout | `mes/siemens-iem/token/delete` | `GET /portal/api/v1/logout` | Invalidates the token (IEM-OS only; not on IEM on Kubernetes) |
| ListDevices | `mes/siemens-iem/device/list` | `GET /portal/api/v1/devices` | query: page=0\&size=50 (send "" for defaults) |
| GetDevice | `mes/siemens-iem/device/get` | `GET /portal/api/v1/devices/{id}` | data.deviceStatus, deviceVersion, deviceTypeId, ... |
| GetDeviceStatistics | `mes/siemens-iem/device-statistics/get` | `GET /portal/api/v1/devices/{id}/statistics` | Last statistics the device sent (app counts, network, resources) |
| ListInstalledApps | `mes/siemens-iem/device-app/list` | `GET /portal/api/v1/devices/installed-apps` | query: deviceid=\<id> (send "" for all devices) |
| ListCatalogApps | `mes/siemens-iem/application/list` | `GET /portal/api/v1/applications` | Catalog applications with their 32-char application ids |
| GetApplication | `mes/siemens-iem/application/get` | `GET /portal/api/v1/applications/{id}` | Application details and versions |
| ListAppConfigs | `mes/siemens-iem/application-config/list` | `GET /portal/api/v1/applications/{id}/configs` | Config ids, template ids and version ids for updateAppConfig |
| DeployApplication | `mes/siemens-iem/application/deploy` | `POST /portal/api/v1/batches` | Install a catalog app on devices; form = multipart infoMap \{"devices":\[...]} -> data = batch id |
| ApplicationCommand | `mes/siemens-iem/application/command` | `POST /portal/api/v1/batches` | operation: installApplication/updateApplication/uninstallApplication/startApplication/restartApplication/stopApplication/updateAppConfig/deleteAppConfig; query: versionId=...\&schedule=... or "" |
| GetBatch | `mes/siemens-iem/batch/get` | `GET /portal/api/v1/batches/{batchId}` | data = READY / PROCESSED |
| ListBatchJobs | `mes/siemens-iem/batch-job/list` | `GET /portal/api/v1/batches/{id}/jobs` | Per-device install jobs of a batch |
| GetInstallJob | `mes/siemens-iem/job/get` | `GET /portal/api/v1/installjobs/{id}` | data = COMPLETED / PENDING / QUEUED / FAILED / EXECUTING / DELETED / DELETING |

Every reply is published on `<topic>/response`.

## Authentication

The Portal API uses a token in the `Authorization` header, sent **as is** (no `Bearer` prefix):

1. Publish to `mes/siemens-iem/token/create` with `{"body": {"username": "...", "password": "..."}}`. Use an IEM user or a technical user with the rights you need. The reply has `data.access_token`, valid for 24 hours.
2. Put that token in `"authorization"` on every other event.

Keep the user name and password in Hub secrets (for example `SIEMENS_IEM_USERNAME` and `SIEMENS_IEM_PASSWORD`) and read them with `GET SECRET`. Never paste them into the connector. A missing or expired token returns `401`.

> [!WARNING]
>
> Many IEM installations use a self-signed certificate (the Siemens examples call `curl --insecure`). The broker host must trust the IEM certificate authority, or every call fails during the TLS handshake.

## Connector

Replace `YOUR_IEM_HOST` with your IEM address (no path). Every endpoint starts with `/portal/api/v1`.

```lot theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE SiemensIEM WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://YOUR_IEM_HOST"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '30'
        WITH DEFAULT_CONTENT_TYPE "application/json"
        # Smoke: Login (POST, technical user) -> VerifyToken, ListDevices, ListCatalogApps (GET); DeployApplication of a harmless app to a test device -> GetBatch / ListBatchJobs / GetInstallJob.
    ADD EVENT Login
        WITH SOURCE_TOPIC "mes/siemens-iem/token/create"
        WITH DESTINATION_TOPIC "mes/siemens-iem/token/create/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/portal/api/v1/login/direct"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
        WITH BODY "{value.json.body}"
    ADD EVENT VerifyToken
        WITH SOURCE_TOPIC "mes/siemens-iem/token/verify"
        WITH DESTINATION_TOPIC "mes/siemens-iem/token/verify/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/auth-tokens/verify"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT Logout
        WITH SOURCE_TOPIC "mes/siemens-iem/token/delete"
        WITH DESTINATION_TOPIC "mes/siemens-iem/token/delete/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/logout"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListDevices
        WITH SOURCE_TOPIC "mes/siemens-iem/device/list"
        WITH DESTINATION_TOPIC "mes/siemens-iem/device/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/devices?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetDevice
        WITH SOURCE_TOPIC "mes/siemens-iem/device/get"
        WITH DESTINATION_TOPIC "mes/siemens-iem/device/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/devices/{value.json.device_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetDeviceStatistics
        WITH SOURCE_TOPIC "mes/siemens-iem/device-statistics/get"
        WITH DESTINATION_TOPIC "mes/siemens-iem/device-statistics/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/devices/{value.json.device_id}/statistics"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListInstalledApps
        WITH SOURCE_TOPIC "mes/siemens-iem/device-app/list"
        WITH DESTINATION_TOPIC "mes/siemens-iem/device-app/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/devices/installed-apps?{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListCatalogApps
        WITH SOURCE_TOPIC "mes/siemens-iem/application/list"
        WITH DESTINATION_TOPIC "mes/siemens-iem/application/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/applications"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetApplication
        WITH SOURCE_TOPIC "mes/siemens-iem/application/get"
        WITH DESTINATION_TOPIC "mes/siemens-iem/application/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/applications/{value.json.app_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListAppConfigs
        WITH SOURCE_TOPIC "mes/siemens-iem/application-config/list"
        WITH DESTINATION_TOPIC "mes/siemens-iem/application-config/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/applications/{value.json.app_id}/configs"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT DeployApplication
        WITH SOURCE_TOPIC "mes/siemens-iem/application/deploy"
        WITH DESTINATION_TOPIC "mes/siemens-iem/application/deploy/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/portal/api/v1/batches?appid={value.json.app_id}&operation=installApplication"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "multipart/form-data; boundary=CorefluxIemBoundary"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.form}"
    ADD EVENT ApplicationCommand
        WITH SOURCE_TOPIC "mes/siemens-iem/application/command"
        WITH DESTINATION_TOPIC "mes/siemens-iem/application/command/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/portal/api/v1/batches?appid={value.json.app_id}&operation={value.json.operation}&{value.json.query}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "multipart/form-data; boundary=CorefluxIemBoundary"
            ADD "Authorization" "{value.json.authorization}"
        WITH BODY "{value.json.form}"
    ADD EVENT GetBatch
        WITH SOURCE_TOPIC "mes/siemens-iem/batch/get"
        WITH DESTINATION_TOPIC "mes/siemens-iem/batch/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/batches/{value.json.batch_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT ListBatchJobs
        WITH SOURCE_TOPIC "mes/siemens-iem/batch-job/list"
        WITH DESTINATION_TOPIC "mes/siemens-iem/batch-job/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/batches/{value.json.batch_id}/jobs"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
    ADD EVENT GetInstallJob
        WITH SOURCE_TOPIC "mes/siemens-iem/job/get"
        WITH DESTINATION_TOPIC "mes/siemens-iem/job/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/portal/api/v1/installjobs/{value.json.job_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "{value.json.authorization}"
```

## Deploying an app

`POST /portal/api/v1/batches` takes `multipart/form-data` with one field, `infoMap` (JSON). The connector sends the fixed boundary `CorefluxIemBoundary`, so `form` carries the complete multipart body with CRLF line breaks:

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "authorization": "<access_token>",
  "app_id": "46d2ac22e41a4b65af55a434c887578e",
  "form": "--CorefluxIemBoundary\r\nContent-Disposition: form-data; name=\"infoMap\"\r\n\r\n{\"devices\":[\"06cdac6c607e447dad16eef9f767a56e\"]}\r\n--CorefluxIemBoundary--\r\n"
}
```

Publish that to `mes/siemens-iem/application/deploy`. The reply is `{"data": "<batch id>"}`. Then:

1. `mes/siemens-iem/batch/get` with `batch_id`: `READY` (batch accepted) or `PROCESSED` (device jobs created).
2. `mes/siemens-iem/batch-job/list` with `batch_id`: one job per device.
3. `mes/siemens-iem/job/get` with `job_id`: `QUEUED`, `EXECUTING`, `COMPLETED`, `FAILED`, ...

`infoMap` can also carry `delayTime` (1 to 60 minutes between devices) and `configs` (for example `[{"configId": "...", "templateId": "..."}]`, ids from `ListAppConfigs`). For other operations use `mes/siemens-iem/application/command` with `operation` set to `updateApplication`, `uninstallApplication`, `startApplication`, `restartApplication`, `stopApplication`, `updateAppConfig` or `deleteAppConfig`, and `query` set to `""` or `versionId=<id>` (developer apps) and `schedule=<ticks>`.

> [!WARNING]
>
> Deploy and command events change what runs on production edge devices. Restrict who may publish to `mes/siemens-iem/application/#` with a broker rule.

## Example actions

Log in twice a day, keep the token in broker state, and poll the device list every five minutes:

```lot theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ACTION SiemensIemLogin
ON EVERY 12 HOURS DO
    SET "user" WITH GET SECRET "SIEMENS_IEM_USERNAME"
    SET "pass" WITH GET SECRET "SIEMENS_IEM_PASSWORD"
    PUBLISH TOPIC "mes/siemens-iem/token/create" WITH { "body": { "username": {user}, "password": {pass} } }

DEFINE ACTION SiemensIemKeepToken
ON TOPIC "mes/siemens-iem/token/create/response" DO
    SET "token" WITH GET JSON "data.access_token" IN PAYLOAD AS STRING
    KEEP TOPIC "state/siemens-iem/token" WITH {token}

DEFINE ACTION SiemensIemPollDevices
ON EVERY 5 MINUTES DO
    SET "token" WITH GET TOPIC "state/siemens-iem/token" AS STRING
    PUBLISH TOPIC "mes/siemens-iem/device/list" WITH { "authorization": {token}, "query": "page=0&size=100" }
```

## Notes

* `ListDevices` takes `query` such as `page=0&size=50`. `ListInstalledApps` takes `deviceid=<id>`, or `""` for all devices.
* Device status is `data.deviceStatus` from `GetDevice`. There is no separate device status endpoint. `GetDeviceStatistics` returns the last statistics the device sent, keyed by timestamp.
* `Logout` works on IEM-OS only (not on IEM on Kubernetes).
* Not included: application import from file and file-based app configs (multipart file uploads), device creation and deletion, device reboot or shutdown jobs, log downloads, projects and companies, and the separate IEM Admin API.

## References

* [IEM Portal API 1.9.0 (OpenAPI)](https://developer.siemens.com/industrial-edge/api/iem/api-portal/v1.9.0/api-portal-1-9-0.html)
* [Portal Public API reference](https://docs.industrial-operations-x.siemens.cloud/r/en-us/portal-public-api)
* [Industrial Edge APIs and SDKs](https://docs.industrial-operations-x.siemens.cloud/p/industrial-edge-apis-sdks)
* [REST API connectors](/latest/lot-language/routes/rest-api-routes)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.