Connect an MQTT broker

Subscribe to a broker and map topics or payload fields to machines and signals.

InduQT subscribes to your broker, reads JSON messages and maps each one to a machine and its signals. The broker must be reachable from the internet; TLS (mqtts:// or wss://) is strongly recommended.

Set up

  1. Create the site and machines

    Create them in the app or with POST /v1/sites and POST /v1/machines. Set each machine's externalId to the name your source uses (for example B-101), so messages can address it without knowing InduQT ids.

  2. Create a broker user for InduQT

    Give it read (subscribe) access to the telemetry topics only.

  3. Add the connector

    In the app: open the site and choose MQTT broker. Or with the API, using a key with the write scope:

    POST /v1/connectors
    curl -X POST "https://api.induqt.ai/v1/connectors" \
      -H "Authorization: Bearer $INDUQT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "siteId": "6f1c2c0e-4b1a-4c55-9d0e-1f2a3b4c5d6e",
      "type": "mqtt",
      "name": "Boiler house broker",
      "config": {
        "url": "mqtts://broker.example.com:8883",
        "topic": "plant/+/telemetry",
        "username": "induqt",
        "password": "…",
        "qos": 1
      },
      "mapping": {
        "machineFrom": "topic",
        "topicLevel": 1,
        "autoCreate": true
      }
    }'
  4. Check it is connected

    GET /v1/connectors shows status, lastMessageAt and lastError.

Settings and mapping

MQTT broker settings
NameDescription
urlrequiredmqtt://, mqtts://, ws:// or wss:// URL of the broker, with port.
topicrequiredTopic filter; + and # wildcards allowed. Several filters separated by commas.
username / passwordBroker credentials. The password is encrypted at rest.
qos0 or 1. Default 0.

Mapping. machineFrom: "topic" (use topicLevel, 0-based) | "payload" (machineField, default "machine") | "fixed" (machine). Values: valuesField (default: every numeric top-level field), timestampField (default "ts"). Sparkplug B is not decoded yet.

Mapping by topic

When the machine is part of the topic, use machineFrom: "topic". Topic levels count from 0: in plant/B-101/telemetry, level 1 is B-101, matched against the machine's externalId.

Mapping by topic
TopicPayloadResult
plant/B-101/telemetry{"ts":"2026-10-27T03:12:09Z","steam_pressure":112.4,"steam_flow":2.1}Machine B-101; signals steam_pressure and steam_flow at 03:12:09Z
plant/B-102/telemetry{"steam_pressure":98.7,"burner_on":true}Machine B-102 (created if autoCreate); time of receipt; burner_on stored as 1
mapping
{
  "machineFrom": "topic",
  "topicLevel": 1,
  "autoCreate": true
}

Mapping by payload

When many machines share one topic, name the machine inside the message and point valuesField at the object holding the numbers.

Message on plant/boilerhouse
{
  "machine": "B-101",
  "ts": "2026-10-27T03:12:09Z",
  "values": {
    "steam_pressure": 112.4,
    "flue_o2": 3.2
  }
}
mapping
{
  "machineFrom": "payload",
  "machineField": "machine",
  "valuesField": "values",
  "timestampField": "ts"
}

For a topic that only ever carries one machine, use { "machineFrom": "fixed", "machine": "B-101" }.

Test with mosquitto_pub

shell
mosquitto_pub -h broker.example.com -p 8883 --capath /etc/ssl/certs \
  -u plant-gateway -P "$MQTT_PASSWORD" -q 1 \
  -t plant/B-101/telemetry \
  -m '{"ts":"2026-10-27T03:12:09Z","steam_pressure":112.4,"steam_flow":2.1}'

Then check the value arrived with GET /v1/machines/{machineId}/latest.

Troubleshooting

Troubleshooting
SymptomLikely cause and fix
Stays pending or shows a connection errorThe broker is not reachable from the internet, the port is blocked, or the scheme is wrong (mqtt:// on a TLS port or the reverse). Self-signed certificates must chain to a public CA.
Not authorizedWrong username or password, or the broker ACL does not allow subscribing to the topic filter.
Connected, but no dataThe topic filter does not match what devices publish (check case and levels), or the payload is not JSON.
Messages arrive but machines do notThe topic level or machineField does not match any externalId. Fix the mapping or set autoCreate: true.
Some values missingOnly numeric top-level fields are read unless valuesField is set. Nested objects and strings are skipped.
Sparkplug B devicesSparkplug B (protobuf) payloads are not decoded yet. Bridge them to JSON, for example with Node-RED, or use the ingest API.