Skip to content
© 2026 The ThingsBoard Authors
Try for free

ThingsBoard Cloud

Choose your data region

Your data stays in the region you choose, for residency and compliance. No credit card required.

Rather run it yourself? Install on your own servers

MQTT Gateway API

A Gateway in ThingsBoard is a special device that acts as a bridge, maintaining a single MQTT connection to ThingsBoard Edge while proxying data for multiple physical devices behind it. The gateway itself is also a standard ThingsBoard device and can use the regular MQTT Device API to publish its own telemetry and attributes.

This API is used by the open-source ThingsBoard IoT Gateway.

Operation Direction Topic
Connect device Gateway → Edge v1/gateway/connect
Disconnect device Gateway → Edge v1/gateway/disconnect
Publish client-side attributes Gateway → Edge v1/gateway/attributes
Request attribute values Gateway → Edge v1/gateway/attributes/request
Receive attribute response Edge → Gateway v1/gateway/attributes/response
Subscribe to attribute updates Edge → Gateway v1/gateway/attributes
Publish telemetry Gateway → Edge v1/gateway/telemetry
Subscribe to RPC Edge → Gateway v1/gateway/rpc
Publish RPC response Gateway → Edge v1/gateway/rpc
Claim devices Gateway → Edge v1/gateway/claim

The examples in this guide use mosquitto_pub and mosquitto_sub from the Mosquitto package.

Terminal window
sudo apt-get install mosquitto-clients

Set up environment variables used in all examples:

Terminal window
export ACCESS_TOKEN=your_gateway_access_token
export EDGE_HOST=your_edge_host_or_ip

Inform ThingsBoard Edge that a device behind the Gateway is connected and ready to exchange data.

Topic: v1/gateway/connect

Payload:

{"device": "Device A", "type": "Sensor A"}
  • device — required. The device name in ThingsBoard.
  • type — optional. Device profile name. Defaults to default if omitted.

Behavior:

  • If the device does not exist, ThingsBoard creates it automatically.
  • If the profile name is provided and does not exist, ThingsBoard creates it automatically.
  • Once connected, ThingsBoard routes shared attribute updates and RPC commands for this device through the Gateway.

Example 1. Connect a device:

Terminal window
mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/connect" \
-u "$ACCESS_TOKEN" -m '{"device": "Device A"}'

Example 2. Connect a device with a specific profile:

Terminal window
mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/connect" \
-u "$ACCESS_TOKEN" -m '{"device": "Device A", "type": "Sensor A"}'

Inform ThingsBoard Edge that a device behind the Gateway is no longer active.

Topic: v1/gateway/disconnect

Payload:

{"device": "Device A"}

Behavior:

  • If the device does not exist, ThingsBoard ignores the message.
  • After processing, ThingsBoard stops routing attribute updates and RPC commands for that device through the Gateway.

Example:

Terminal window
mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/disconnect" \
-u "$ACCESS_TOKEN" -m '{"device": "Device A"}'

The Gateway can publish client-side attributes, request attribute values, and subscribe to shared attribute updates for devices behind it. See Working with attributes for attribute type details.

Upload client-side attributes for one or more devices. All keys in the payload are stored as client-side attributes.

Topic: v1/gateway/attributes

Payload:

{
"Device A": {"attribute1": "value1", "attribute2": 42},
"Device B": {"attribute1": "value1", "attribute2": 42}
}

Behavior:

  • If the device does not exist, ThingsBoard creates it with the default profile.
  • New attribute keys are created; existing keys are updated.

Example:

Terminal window
mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/attributes" \
-u "$ACCESS_TOKEN" \
-m '{"Device A": {"fw_version": "1.0.3", "battery": 87}}'

Subscribe to the response topic first, then publish the request. Both have to happen in the same MQTT session, so use mosquitto_rr: it subscribes, publishes the request and waits for the response over one connection.

Subscribe topic: v1/gateway/attributes/response

Publish topic: v1/gateway/attributes/request

Request payload:

{
"id": 1,
"device": "Device A",
"clientKeys": "fw_version,battery",
"sharedKeys": "targetFwVersion"
}
  • id — required. Integer request identifier. The response echoes the same id.
  • device — required. The device name in ThingsBoard.
  • clientKeys — optional. Comma-separated client-side attribute keys. Set to "" (empty string) to retrieve all client-side attributes. Omit to exclude client attributes from the response.
  • sharedKeys — optional. Comma-separated shared attribute keys. Set to "" (empty string) to retrieve all shared attributes. Omit to exclude shared attributes from the response.

Omitting both clientKeys and sharedKeys (sending only id and device) returns all client and all shared attributes in a single scope-separated response.

Response payload:

{
"id": 1,
"device": "Device A",
"client": {"fw_version": "1.0.3", "battery": 87},
"shared": {"targetFwVersion": "2.0.1"}
}

The response is scope-separated: client contains client-side attributes, shared contains shared attributes. A scope appears only if it returned at least one attribute, so it is absent both when you did not ask for it and when the device has nothing in it.

Example:

Terminal window
mosquitto_rr -d -q 1 -h "$EDGE_HOST" -p 1883 \
-t "v1/gateway/attributes/request" \
-e "v1/gateway/attributes/response" \
-u "$ACCESS_TOKEN" \
-m '{"id":1,"device":"Device A","clientKeys":"fw_version,battery","sharedKeys":"targetFwVersion"}'

To retrieve every attribute of one scope, pass an empty string — '{"id":1,"device":"Device A","sharedKeys":""}' returns all shared attributes.

Subscribe to receive shared attribute changes pushed by ThingsBoard for devices behind the Gateway.

Subscribe topic: v1/gateway/attributes

Message format:

{
"device": "Device A",
"data": {"attribute1": "value1", "attribute2": 42}
}
  • device — the device name in ThingsBoard.
  • data — map of updated shared attribute keys and values.

Publish time-series data for one or more devices in a single message.

Topic: v1/gateway/telemetry

Payload:

{
"Device A": [
{"ts": 1483228800000, "values": {"temperature": 42, "humidity": 80}},
{"ts": 1483228801000, "values": {"temperature": 43, "humidity": 82}}
],
"Device B": [
{"ts": 1483228800000, "values": {"temperature": 42, "humidity": 80}}
]
}
  • ts — optional. Unix timestamp in milliseconds. If omitted, the server assigns the current time.
  • values — required. Key-value map of telemetry fields.

Behavior:

  • If the device does not exist, ThingsBoard creates it with the default profile.
  • New telemetry keys are created; data is stored at the provided timestamps.

Example:

Terminal window
mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/telemetry" \
-u "$ACCESS_TOKEN" \
-m '{"Device A": [{"ts": 1700000000000, "values": {"temperature": 23.5, "humidity": 61}}]}'

Receive RPC commands from ThingsBoard for devices behind the Gateway and publish responses.

Subscribe topic: v1/gateway/rpc

Request message format:

{"device": "Device A", "data": {"id": 1, "method": "toggle_gpio", "params": {"pin": 1}}}

Response topic: v1/gateway/rpc

Response message format:

{"device": "Device A", "id": 1, "data": {"success": true}}
  • device — the device name in ThingsBoard.
  • id — the request identifier. Must match the id from the request.
  • data — response payload.

Initiate the claiming process so end users can take ownership of pre-provisioned devices.

Topic: v1/gateway/claim

Payload:

{
"Device A": {"secretKey": "value_A", "durationMs": 60000},
"Device B": {"secretKey": "value_B", "durationMs": 60000}
}

Per-device parameters:

  • secretKey — optional. Secret key assigned to the device. Defaults to an empty string.
  • durationMs — optional. Claiming window in milliseconds. Defaults to the device.claim.duration system parameter.

Example:

Terminal window
mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/claim" \
-u "$ACCESS_TOKEN" \
-m '{"Device A": {"secretKey": "mySecret", "durationMs": 60000}}'

The MQTT transport can be fully customized for specific use cases by modifying the corresponding transport module.