Skip to content

Cookie preferences

We use cookies for our own analytics, to see how our campaigns perform and, if you allow it, to load content from other services such as the Google site search. We never sell your data. Necessary cookies keep the site working and cannot be switched off. See our Cookie Policy for details and our Privacy Policy for how we handle personal data.

Security, load balancing and remembering your cookie choice.

Show us which pages people read, how they find the site and where they get stuck, so we can improve it (Google Analytics, Microsoft Clarity).

Show us which of our ad campaigns bring visitors to the site and remember the campaign or partner link you arrived from (Google Ads, LinkedIn, Meta, partner program). We do not use these cookies to build advertising profiles.

Load the site search from Google when you use it. Google sets its own cookies and shows ads in the search results.

© 2026 The ThingsBoard Authors
22.6k 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

AWS IoT Integration

AWS IoT Integration connects ThingsBoard to AWS IoT Core, the managed MQTT broker of AWS. ThingsBoard connects as an MQTT client over mutual TLS and subscribes to the topics you configure. An uplink data converter transforms each message into device or asset data, including telemetry and attributes. ThingsBoard can also publish downlink messages to AWS IoT Core for devices to consume.

Use AWS IoT Integration when:

  • Devices already publish to AWS IoT Core and you want their data in ThingsBoard without changing the firmware.
  • One subscription must serve many devices: the converter resolves each device from the topic or the payload.
  • You need to send commands to devices through AWS IoT Core.
  1. Receive data. A device publishes a message to AWS IoT Core. The integration is subscribed to that topic and receives the message.
  2. Decode the payload. The uplink converter uses the payload and topic to identify the device or asset and extract attributes and telemetry.
  3. Process the message. ThingsBoard processes the converted data through the Rule Engine. If Allow create devices or assets is enabled, ThingsBoard creates an entity that does not exist yet.
  4. Send downlink data (optional). The Rule Engine passes a message to the integration. The downlink converter encodes it, and the integration publishes it to AWS IoT Core on the downlink topic.
  • Access to ThingsBoard or ThingsBoard Cloud with integrations enabled for your tenant.
  • Permission to create integrations and data converters.
  • An AWS account with permission to create AWS IoT policies, things, and certificates.
  • Outbound TCP port 8883 open from the ThingsBoard server (or the remote integration host) to AWS IoT Core.

In the AWS IoT console, create a policy, a thing with a certificate, and copy the device data endpoint. ThingsBoard authenticates with the certificate and its private key, and verifies AWS IoT Core with the Amazon Root CA certificate.

A policy lists the AWS IoT actions (Connect, Publish, Subscribe, Receive) that the certificate may perform. See AWS IoT Core policies.

  1. Go to Manage ⇾ Security ⇾ Policies and click Create policy.
  2. Enter a Policy name, for example thingsboard-integration-policy, and click JSON to switch the Policy document from Builder to the JSON editor.
  3. Paste the policy below. Replace YOUR_REGION and YOUR_AWS_ID with your AWS Region code and account ID, for example eu-north-1 and 111122223333. The Region menu in the top-right corner of the console shows the Region name (for example, Europe (Stockholm)); open it to see the code next to the name. The account ID is in the account menu next to it.
  4. Click Create.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["iot:Publish", "iot:Receive"],
"Resource": ["arn:aws:iot:YOUR_REGION:YOUR_AWS_ID:topic/*"]
},
{
"Effect": "Allow",
"Action": ["iot:Subscribe"],
"Resource": ["arn:aws:iot:YOUR_REGION:YOUR_AWS_ID:topicfilter/*"]
},
{
"Effect": "Allow",
"Action": ["iot:Connect"],
"Resource": ["arn:aws:iot:YOUR_REGION:YOUR_AWS_ID:client/*"]
}
]
}

A thing represents a device in AWS IoT. ThingsBoard connects with the certificate attached to it. See Create AWS IoT resources.

  1. Go to Manage ⇾ All devices ⇾ Things and click Create things.
  2. Select Create single thing and click Next.
  3. Enter a Thing name, for example thingsboard-integration. Leave the Additional configurations and Device Shadow sections at their defaults, and click Next.
  4. Select Auto-generate a new certificate (recommended) and click Next.
  5. Select the policy you created and click Create thing.
  6. In the Download certificates and keys window, click Download all, or download at least these three files:
    • Device certificate (*-certificate.pem.crt).
    • Private key file (*-private.pem.key).
    • Amazon Root CA 1 (AmazonRootCA1.pem, RSA 2048 bit key).
  7. Click Done.

The device data endpoint is the MQTT hostname of AWS IoT Core for your account and Region.

  1. In the left menu of the AWS IoT console, go to Connect ⇾ Domain configurations.
  2. In the row iot:Data-ATS, copy the Domain name, for example a312hmjca0kjxk-ats.iot.eu-north-1.amazonaws.com.

You now have everything the integration needs:

Value Example Integration field
Device data endpoint a312hmjca0kjxk-ats.iot.eu-north-1.amazonaws.com AWS IoT Endpoint
Amazon Root CA 1 AmazonRootCA1.pem CA certificate file
Device certificate *.pem.crt Certificate file
Private key *-private.pem.key Private key file

Create the uplink converter, assign it to a new AWS IoT integration, and publish a test message.

The uplink converter receives each MQTT message as a byte array plus its topic, resolves the target device, and returns its telemetry and attributes. AWS IoT Integration uses the Generic converter: you write the decoder in TBEL or JavaScript. For converter types and the full decoder reference, see Uplink data converter.

This guide uses a thermostat that publishes its readings to tb/aws/iot/telemetry/thermostat/Thermostat-01:

{
"ts": 1791901200000,
"temperature": 25.3,
"humidity": 62.8,
"battery": 78.5,
"fwVersion": "1.4.2",
"location": {
"latitude": 37.7749,
"longitude": -122.4194
}
}

ts is the measurement time in milliseconds. Replace it with the current time, or remove it: without ts, ThingsBoard uses the time the message arrives.

Devices publish their data under tb/aws/iot/telemetry/ and receive commands under tb/aws/iot/commands/. Keep the two namespaces separate: the integration subscribes only to the data topics, so it does not receive its own downlink messages back as uplinks.

The topic structure tb/aws/iot/telemetry/{deviceType}/{deviceName} is a convention of this guide, not an AWS IoT requirement. If your devices publish to other topics, adapt the decoder and the topic filter. The decoder has no fallback values: a message whose topic has no device type or device name is rejected, and no device is created.

  1. Go to Integrations ⇾ Data converters and click + Add data converter ⇾ Create new converter.

  2. Converter type — keep Uplink.

  3. Integration type — select AWS IoT.

  4. Name — enter a name, for example AWS IoT Uplink Converter.

  5. Main decoding configuration — the editor opens with the default AWS IoT template, which already takes the device name and type from the topic. Replace it with the decoder below. The decoder takes the device name and type from the last two topic segments (.../{deviceType}/{deviceName}), stores fwVersion and the location coordinates as attributes and temperature, humidity, and battery as telemetry, and uses the device timestamp ts if the payload has one. If the topic is missing or its last two segments are empty, the decoder stops with an error. The editor opens in TBEL; use the TBEL / JS toggle to switch to JavaScript.

    /** Decoder **/
    // ThingsBoard passes the MQTT topic of each AWS IoT message in metadata.topic.
    // This example uses the last two topic segments to identify the device:
    //
    // tb/aws/iot/telemetry/thermostat/Thermostat-01
    // ^^^^^^^^^^ ^^^^^^^^^^^^^
    // type name
    // Get the MQTT topic and reject messages if it is missing or empty.
    var topic = metadata.topic;
    if (topic == null || topic.trim().isEmpty()) {
    raiseError("MQTT topic is missing or empty");
    }

    To adapt:

    • Other topic structure — change the indexes in topicParts[n - 1] and topicParts[n - 2], and change the topic filter to match. With the filter tb/aws/iot/telemetry/+/+, only topics with exactly two levels after tb/aws/iot/telemetry/ reach the decoder. With tb/aws/iot/telemetry/#, a topic such as tb/aws/iot/telemetry/Thermostat-01 would also reach it, and the decoder would take telemetry as the device type.
    • Device name in the payload — use a payload field instead, for example data.deviceId.
    • Other telemetry — add keys to telemetry, for example pressure: data.pressure.
    • Other device properties — add them to attributes, for example serialNumber: data.serialNumber.
    • Update-only keys — in Advanced decoding parameters, the Update only keys list of a new AWS IoT converter already contains fwVersion, latitude, and longitude: these keys are stored only when their value changes. Add other keys that rarely change, or remove keys that you want to store with every message.
  6. Click Test decoder function and check the result (see Test the Decoder).

  7. Click Add.

Decoder Inputs

The decoder signature is function decoder(payload, metadata): object | object[].

Variable Type Content
payload byte array The MQTT message body.
metadata {[key: string]: string} topic — the topic the message arrived on, for example tb/aws/iot/telemetry/thermostat/Thermostat-01. Also integrationName and the key–value pairs from the integration’s Metadata field.

With a wildcard topic filter, topic holds the actual topic of the message, not the filter.

For field renaming, nested values, and non-JSON payloads, see Common scripting patterns.

Test the Decoder

Click Test decoder function below the editor. Set Payload content type to JSON and paste the sample payload. The Metadata already has a topic row with a sample AWS IoT topic; set it to the topic of your device:

Key Value
topic tb/aws/iot/telemetry/thermostat/Thermostat-01

Click Test. The Output panel shows:

{
"deviceName": "Thermostat-01",
"deviceType": "thermostat",
"attributes": {
"fwVersion": "1.4.2",
"latitude": 37.7749,
"longitude": -122.4194
},
"telemetry": {
"ts": 1791901200000,
"values": {
"temperature": 25.3,
"humidity": 62.8,
"battery": 78.5
}
}
}

ts comes from the payload; without it, ts is the time of the test. The decoder needs the topic row: real messages always carry the topic. If you delete the row, the test fails with MQTT topic is missing or empty; with a topic such as thermostat or tb/aws/iot/telemetry/thermostat/, it fails with MQTT topic must contain device type and device name.

  1. Go to Integrations ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Integration type — select AWS IoT.
    • Name — enter a name, for example AWS IoT integration.
    • Enable integration and Allow create devices or assets — keep both on, so the device is created on its first uplink.
    • Click Next.
  3. Uplink data converter:
    • Click Select existing and choose AWS IoT Uplink Converter.
    • Alternatively, click Create new to write a decoder here.
    • Click Next.
  4. Downlink data converter:
  5. Connection:
    • AWS IoT Endpoint — paste the device data endpoint: the host name only, without https:// or a port.
    • CA certificate file, Certificate file, Private key file — upload AmazonRootCA1.pem, the *-certificate.pem.crt certificate, and the *-private.pem.key key. See Credentials.
    • Topic filters — replace the default # with tb/aws/iot/telemetry/+/+.
    • Leave the other parameters at their defaults. See Connection Settings for details.
  6. Optionally, click Check connection to test the endpoint and the certificates before you save.
  7. Click Add.

ThingsBoard always connects to AWS IoT Core on port 8883 over TLS, with a clean session.

Parameter Description
AWS IoT Endpoint Device data endpoint, in the form {prefix}-ats.iot.{region}.amazonaws.com: a host name only, without https:// or a port. Required.
Credentials Certificate files for mutual TLS. See Credentials.
Topic filters One or more subscriptions, each with a Topic and QoS. Default: # with QoS 0. Click Add topic filter to add more. See Topic Filters.
Execute remotely Runs the integration as a separate process outside the ThingsBoard cluster. ThingsBoard generates an Integration key and Integration secret for it. See Remote Integration.

Advanced settings

Parameter Default Description
Protocol version MQTT 3.1.1 MQTT 3.1, MQTT 3.1.1, or MQTT 5.0. AWS IoT Core supports 3.1.1 and 5.0.
Client ID empty Empty: an ID is generated. A custom ID must be unique and at most 128 characters long — AWS IoT Core disconnects a client when another one connects with the same ID.
Max bytes in message 32368 Maximum size of an incoming message, in bytes (1–256,000,000). A bigger message is dropped, and the integration Events tab shows an uplink with status ERROR. AWS IoT Core itself limits messages to 128 KB. The converter script has its own input limit: TBEL_MAX_TOTAL_ARGS_SIZE (default 100,000) or JS_MAX_TOTAL_ARGS_SIZE (default 150,000) in thingsboard.yml. In tests, TBEL decoders failed from about 80 KB and JavaScript decoders from about 95 KB.
Connection timeout (sec) 10 Time to wait for AWS IoT Core to accept the connection (1–200).
Downlink topic pattern ${topic} Topic for downlink messages. Each ${key} is replaced with the value of key from the downlink converter’s output metadata.
Description — Free-text description.
Metadata — Key–value pairs added to the metadata of every message from this integration.

AWS IoT Integration supports only certificate (PEM) credentials. Upload each file (Browse file) or take it from Secrets storage.

Field File
CA certificate file AmazonRootCA1.pem. Verifies AWS IoT Core.
Certificate file Device certificate, *.pem.crt.
Private key file Private key, *-private.pem.key.
Private key password Only for an encrypted key. Keys generated by AWS are not encrypted; leave it empty.

The certificate must be Active and have the policy attached. See X.509 client certificates.

The integration subscribes to all topic filters when it connects. Subscribe to a dedicated namespace rather than #, so the integration receives only ThingsBoard traffic. Do not include the downlink topics in the filters: with tb/aws/iot/#, the integration would also receive its own commands from tb/aws/iot/commands/... and process them as uplinks.

ThingsBoard checks the filters when you save the integration: # must be the last level, and + must take a whole level.

Wildcard Matches Example filter Matching topics
+ Exactly one level tb/aws/iot/telemetry/+/+ tb/aws/iot/telemetry/thermostat/Thermostat-01, tb/aws/iot/telemetry/meter/Meter-01
# All remaining levels, any number; must be last tb/aws/iot/telemetry/# The topics above, and also tb/aws/iot/telemetry/Thermostat-01 and tb/aws/iot/telemetry/site-1/thermostat/Thermostat-01

This guide uses tb/aws/iot/telemetry/+/+: the integration receives only topics with a device type and a device name, in the structure the decoder expects. Messages on topics with fewer or more levels are not delivered to ThingsBoard and do not appear in the integration Events.

QoS Name Delivery
0 At most once No acknowledgment. A message may be lost.
1 At least once Acknowledged. A message may arrive twice.

AWS IoT Core does not support QoS 2, so the integration does not offer it. If a subscription fails, for example because the policy denies iot:Subscribe for the filter, the integration shows an error status with the reason. See MQTT topics.

Publish a message to AWS IoT Core, then confirm that ThingsBoard decoded it and created the device.

Publish the sample payload to tb/aws/iot/telemetry/thermostat/Thermostat-01 with the AWS IoT MQTT test client or the AWS CLI. ts is the measurement time in milliseconds. Replace it with the current time, or remove it: without ts, ThingsBoard uses the time the message arrives.

  1. In the AWS IoT console, go to Test ⇾ MQTT test client. The client connects automatically (Connection details: Connected). Open the Publish to a topic tab.
  2. In Topic name, enter tb/aws/iot/telemetry/thermostat/Thermostat-01.
  3. Paste the sample payload into Message payload.
  4. Click Publish.
  • Integration events — go to Integrations ⇾ Integrations, open the integration, and click the Events tab. The uplink appears with status OK. Click ⋅⋅⋅ in the Message column to see the topic and payload.
  • Converter events — open AWS IoT Uplink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the received payload, Out shows the decoded result, and Metadata shows the topic and integration name.
  • Device — go to Devices & assets ⇾ Devices. The integration has created Thermostat-01 with type thermostat. Open it and confirm temperature, humidity, and battery on the Latest telemetry tab, and fwVersion, latitude, and longitude on the Attributes tab, in the Client attributes scope.

ThingsBoard publishes downlinks to AWS IoT Core when the Rule Engine routes a message to the integration — for example, after a shared attribute update. Downlinks are always published with QoS 1. The topic comes from the Downlink topic pattern: with the default ${topic}, it is the topic value in the downlink converter’s output metadata. If a placeholder of the pattern has no value in the output metadata, or the topic contains + or #, the downlink is not published and the integration Events tab shows a Downlink event with status ERROR.

The downlink converter turns a Rule Engine message into an MQTT payload. For the full encoder reference, see Downlink data converter.

The encoder returns:

  • contentType — JSON, TEXT, or BINARY.
  • data — the payload to publish.
  • metadata — values for the Downlink topic pattern placeholders, for example topic. Use a topic outside the subscribed data topics, for example tb/aws/iot/commands/{deviceName}.

For RPC commands, msg.method and msg.params are available. msg.params is a string — use parseFloat(msg.params) or JSON.parse(msg.params) to get a number or an object.

  1. Open the integration in Integrations ⇾ Integrations and click Toggle edit mode (pencil icon).
  2. In the Downlink data converter field, click Create new. The Downlink converter type and AWS IoT integration type are preselected.
  3. Enter a name, for example AWS IoT Downlink Converter.
  4. Main encoding configuration — the editor opens with the default AWS IoT encoder, which is the encoder below. Keep it, or write your own. The editor opens in TBEL; use the TBEL / JS toggle to switch to JavaScript.
  5. To record downlink events, click the debug icon next to the name, select All messages, and click Apply.
  6. Click Add, then Apply changes.

Encoder used in this guide:

/** Encoder **/
// Publish the ThingsBoard message as JSON to the device command topic.
// metadata.topic is read by the integration when Downlink topic pattern is ${topic}.
// Get the device name without surrounding spaces and reject the message if it is missing or empty.
// The rule chain adds deviceName to the metadata, for example with an originator fields node.
var deviceName = metadata.deviceName != null ? metadata.deviceName.trim() : null;
if (deviceName == null || deviceName.isEmpty()) {
raiseError("Message metadata has no deviceName");
}
var result = {
// Specify the downlink payload format: JSON, TEXT, or BINARY.
contentType: "JSON",
// Serialize the incoming message and use it as the MQTT payload.
data: JSON.stringify(msg),
// Build a per-device command topic in the same namespace as the uplink.
metadata: {
topic: "tb/aws/iot/commands/" + deviceName
}
};
return result;

To adapt:

  • Other payload — build the object the device expects instead of msg, for example { "interval": msg.temperatureUploadFrequency }.
  • Non-JSON payload — set contentType to TEXT for a plain string, or BINARY with a Base64-encoded string.
  • Other message types — branch on msgType to handle other Rule Engine message types.
  • Device name check — the encoder stops with the error Message metadata has no deviceName if the message has no deviceName in its metadata, so a command is never published to tb/aws/iot/commands/null. The rule chain adds deviceName with an originator fields node; see Configure the Root Rule Chain.

The encoder builds the topic from deviceName, so the rule chain first adds the device name to the message metadata.

  1. Go to Data processing ⇾ Rule chains and open the Root Rule Chain.
  2. From the Enrichment section, drag an originator fields node onto the canvas.
  3. Enter a Name (for example, Retrieve device name) and map the source fields:
    • Name ⇾ deviceName
    • Add mapped originator fields to ⇾ Metadata
    • Click Add.
  4. Connect the message type switch node to the originator fields node with the Attributes Updated relation.
  5. From the Action section, drag an integration downlink node onto the canvas.
  6. Enter a Name (for example, Downlink to AWS IoT integration), select your AWS IoT integration, and click Add.
  7. Connect the originator fields node to the integration downlink node with the Success relation.
  8. Click Apply changes.

Subscribe to the command topic, then update a shared attribute to trigger a downlink.

  1. In the AWS IoT console, go to Test ⇾ MQTT test client, open the Subscribe to a topic tab, enter tb/aws/iot/commands/# in Topic filter, and click Subscribe. The note You cannot publish messages to a wildcard topic only means that you cannot publish to this filter from the same panel; receiving works.
  2. In ThingsBoard, go to Devices & assets ⇾ Devices, select Thermostat-01, and open the Attributes tab.
  3. Select Shared attributes and click +.
  4. Set Key to temperatureUploadFrequency, Type to Integer, Value to 60, and click Add. ThingsBoard publishes the downlink.
  • AWS IoT console, MQTT test client — the tb/aws/iot/commands/Thermostat-01 topic shows the payload:

    {"temperatureUploadFrequency":60}
  • ThingsBoard, converter events — go to Integrations ⇾ Data converters, open the downlink converter, and select the Events tab. In shows the Rule Engine message, Out shows the encoded payload, and Metadata shows the topic and integration name.

Symptom Cause Fix
Integration status: unknown host Wrong AWS IoT Endpoint. Copy the endpoint again from Connect ⇾ Domain configurations (row iot:Data-ATS). Enter the host name only, without https:// or a port.
Integration status: the server certificate is not trusted Wrong CA certificate file. Upload AmazonRootCA1.pem (Amazon Root CA 1, RSA).
Integration status: the certificate and the private key do not match, or the key cannot be read The certificate and private key belong to different things, or the key file is damaged. Upload the certificate and key downloaded for the same thing.
Integration status: connection refused (not authorized) The certificate is inactive or has no policy, or the policy denies iot:Connect. In the AWS IoT console, check that the certificate is Active and that the policy is attached and allows iot:Connect.
Integration status: connection timeout, on a self-hosted server Outbound port 8883 is blocked. Open TCP 8883 to AWS IoT Core, or use a Remote Integration.
Integration status: the connection is lost and restored again and again Another client uses the same Client ID. Clear Client ID to get a generated one, or make it unique.
Integration status: subscription failed The policy denies iot:Subscribe or iot:Receive for the topic filter. Check the policy resources: topicfilter/... for iot:Subscribe, topic/... for iot:Receive.
No messages received, status is Active No topic filter matches the published topic, for example the topic has fewer or more levels than the filter. Check the topic filters. tb/aws/iot/telemetry/+/+ matches tb/aws/iot/telemetry/thermostat/Thermostat-01, but not tb/aws/iot/telemetry/Thermostat-01 or tb/aws/iot/telemetry/site-1/thermostat/Thermostat-01.
Uplinks of the integration’s own commands The topic filters include the downlink topics, for example tb/aws/iot/# with commands in tb/aws/iot/commands/.... Use separate namespaces for data and commands, for example tb/aws/iot/telemetry/+/+ for the filter.
Decoder error, no device created The topic has no device type or device name (for example, it ends with /), the test has no topic row, or the payload is not JSON. Open the converter’s Events tab and read the Error column. To see the decoder’s error message, run the same payload and topic in Test decoder function. Publish to tb/aws/iot/telemetry/{deviceType}/{deviceName}.
Device not created deviceName is empty or undefined. Check Out in the converter events.
Uplink event with status ERROR: message too large The message exceeds Max bytes in message (default 32,368 bytes). Raise Max bytes in message in Advanced settings, or send smaller messages. For messages above about 80 KB, also raise TBEL_MAX_TOTAL_ARGS_SIZE or JS_MAX_TOTAL_ARGS_SIZE in thingsboard.yml.
Downlink not received The rule chain does not reach the integration downlink node, or the topic differs from the subscription. Check the Root Rule Chain wiring and the topic in the integration’s Events. Check that the policy allows iot:Publish on that topic.
Downlink event with status ERROR: unresolved placeholder The downlink converter output metadata has no value for a placeholder of Downlink topic pattern, for example topic. Return metadata.topic from the encoder, or change the pattern.
Downlink event with status ERROR: Message metadata has no deviceName The message metadata has no deviceName, so the encoder stops and the downlink is not published. Add the originator fields node before the integration downlink node.

To read debug events, open the integration or converter, click Events, and select an event: In is the received data, Out is the converter result, and Error holds the error text.