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

The Things Stack Industries Integration

The Things Stack Industries Integration connects ThingsBoard to The Things Stack Cloud or Enterprise, the LoRaWAN network server of The Things Industries. ThingsBoard connects to the MQTT server of your The Things Stack tenant as a client and subscribes to the uplinks of your application. An uplink data converter decodes each uplink into telemetry and attributes. For downlink, ThingsBoard publishes the encoded command to the same MQTT server, and The Things Stack delivers it to the device.

Use The Things Stack Industries Integration when:

  • Your LoRaWAN devices are registered in an application on a private The Things Stack tenant, Cloud or Enterprise. For the public The Things Network, use the The Things Stack Community integration instead.
  • You want ThingsBoard to create a device for every end device that sends data, named after its DevEUI.
  • You need to send commands from ThingsBoard to those devices, for example when a shared attribute changes.
  1. Receive data. The device sends an uplink through a LoRaWAN gateway to The Things Stack. The Things Stack publishes it as a JSON message to the topic v3/{application}@{tenant}/devices/{device}/up of its MQTT server, where the integration has subscribed.
  2. Unwrap the message. The uplink converter takes the device payload out of the message and extracts the network fields, such as the DevEUI, the frame port, and the signal quality, into the metadata.
  3. Decode the payload. The decoder turns the payload into telemetry and attributes. The converter adds the network fields you list and sets the device name, profile, and label. If Allow create devices or assets is on, ThingsBoard creates the device on its first uplink.
  4. Send a command (optional). The Rule Engine passes a message to the integration. The downlink converter encodes it, and ThingsBoard publishes it right away to v3/{application}@{tenant}/devices/{device}/down/push. The Things Stack queues it and sends it to the device.
  • Access to ThingsBoard or ThingsBoard Cloud with integrations enabled for your tenant.
  • Permission to create integrations and data converters, and to edit rule chains for downlink.
  • An account on a The Things Stack Cloud or Enterprise tenant, with the right to create applications, end devices, and API keys.
  • The MQTT server of the tenant must be reachable from ThingsBoard. ThingsBoard Cloud connects only to public addresses. For a server in a private network, use a Remote Integration.

Create an application, get its MQTT credentials, and register an end device. This guide uses a test device whose uplinks you simulate in The Things Stack Console, so you can test the integration without hardware.

  1. Sign in to the Console of your The Things Stack tenant.
  2. Go to Applications and click Add application.
  3. Enter an Application ID, for example my-thingsboard.
  4. Click Create application.

The Things Stack runs an MQTT server for every tenant. ThingsBoard signs in to it with the application’s MQTT username and an API key as the password.

  1. In the application, go to Other integrations ⇾ MQTT.
  2. Copy the Public TLS address, for example thingsboard-test.eu1.cloud.thethings.industries:8883. You need the host part for the integration.
  3. Copy the Username. It has the form {applicationId}@{tenantId}, for example my-thingsboard@thingsboard-test.
  4. Click Generate new API key and copy the key. It is the Password.

Register a test device with ABP (Activation by Personalization), so you can simulate uplinks right away without a join procedure. For real devices, use OTAA (Over-the-Air Activation): it creates new session keys on every join. See Adding devices in The Things Stack documentation.

  1. In the application, go to End devices and click Register end device.
  2. Under Input method, select Enter end device specifics manually.
  3. Select the Frequency plan, for example Europe 863-870 MHz (SF9 for RX2 - recommended), the LoRaWAN version, for example LoRaWAN Specification 1.0.0, and the Regional Parameters version if the Console asks for it.
  4. Click Show advanced activation, LoRaWAN class and cluster settings and select Activation by personalization (ABP). Keep the other settings.
  5. Under Provisioning information, click Generate next to DevEUI, Device address, AppSKey, and NwkSKey. The DevEUI becomes part of the device name in ThingsBoard.
  6. Enter an End device ID, for example thermostat-a. ThingsBoard uses it to address downlinks.
  7. Click Register end device.

Set Up The Things Stack Industries Integration

Section titled “Set Up The Things Stack Industries Integration”

Create the uplink converter, then the integration with the MQTT credentials.

The Things Stack Industries Integration uses the Typed uplink converter. ThingsBoard selects it for this integration type, and you cannot change it later. The converter unwraps The Things Stack message first and passes the decoder only the device payload, with the network fields in the metadata. The name, profile, and label of the device, and the network fields to store, are set in the form, not in the script. For details, see Typed uplink converter.

Write the decoder yourself, or take a ready-made one for your device model from the Converters Library.

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

  2. Converter type — keep Uplink.

  3. Integration type — select The Things Stack Industries.

  4. Keep Create new.

  5. Name — enter a name, for example TTI Uplink Converter.

  6. Main decoding configuration:

    • Entity type — keep Device.
    • Device name — keep Device $eui. $eui is replaced with the DevEUI from the metadata, for example Device 70B3D57ED80054FE. You can use any metadata key from Decoder Inputs as $key.
    • The editor below the name opens in TBEL with the default decoder. Keep it: it reads a serial number, battery level, temperature, and saturation from an 8-byte payload. Use the TBEL / JS toggle to switch to JavaScript.
    /**
    * Decodes the incoming payload and returns a structured object containing telemetry data and attributes.
    *
    * @param {byte[]} input - The raw payload received as an array of bytes.
    * @returns {Object} output - The structured output with decoded telemetry and attributes.
    */
    function decodePayload(input) {
    // Initialize the output object with empty attributes and telemetry for clarity.
    var result = { attributes: {}, telemetry: {}};
    // Detect input type and normalize to byte array
    var bytes;
    if (metadata.payloadFormat == 'JSON') {
    // payloadFormat is 'JSON' when The Things Industries payload formatters are configured on the application or device level.
    // In that case, decoded_payload is a JSON object produced by your formatter.
    // This template assumes the formatter returns { "bytes": [...] } with the raw byte array.
    // If your formatter returns pre-decoded values in a different structure,
    // update this section to extract the values directly from 'parsed' instead.

    The decoder reads these bytes:

    Bytes Key Stored as Value
    0–3 sn attribute Serial number
    4 battery telemetry Battery level
    5–6 temperature telemetry Raw value divided by 100
    7 saturation telemetry Saturation level

    To adapt:

    • Byte layout — change the offset and length in each parseBytesToInt() call to match your device payload.
    • Payload formatter — if the application or the device in The Things Stack has an uplink payload formatter, the decoder receives the formatter output as JSON, and metadata.payloadFormat is JSON. Read the values from parsed instead, for example values: { temperature: parsed.temperature }.
    • Device name or profile from the payload — set result.name or result.profile in the script. They override the form.
  7. Advanced decoding parameters — ThingsBoard fills them for The Things Stack Industries. Keep them for this guide:

    • Device profile name — $applicationId, the application ID, for example my-thingsboard.
    • Device label — $deviceId, the end device ID, for example thermostat-a. The downlink in this guide reads the end device ID from the label.
    • Customer name and Device group name — empty.
    • Telemetry — fCnt, data, decoded, latitude, longitude, altitude, rssi, snr, and channel.
    • Attributes and Update only keys list — eui, devAddr, fPort, bandwidth, spreadingFactor, codeRate, frequency, brandId, modelId, hardwareVersion, firmwareVersion, attributes, and tenantId.

    The Telemetry and Attributes lists add these metadata keys to the decoder output, next to the keys that the decoder returns. A key is added only if the uplink has it and the decoder did not return a key with the same name. Keys in the Update only keys list are stored only when their value changes.

  8. Click Test payload decoder and check the result (see Test the Decoder).

  9. Click Add.

Decoder Inputs

Variable Type Content
payload byte array The device payload. Without a payload formatter, the bytes of uplink_message.frm_payload, decoded from Base64. With a formatter, the JSON of uplink_message.decoded_payload.
metadata object The network fields that the converter extracts from the message, payloadFormat, ts, and the integration’s own keys: integrationName, topic, and the key–value pairs from the integration’s Metadata field. An integration key overrides a network field with the same name.

The Things Stack sends each uplink as a JSON message. A simulated uplink from the test device looks like this:

{
"end_device_ids": {
"device_id": "thermostat-a",
"application_ids": {
"application_id": "my-thingsboard"
},
"dev_eui": "70B3D57ED80054FE",
"dev_addr": "260B1A2C"
},
"correlation_ids": ["as:up:01JB8Q4V0R5Y7Z2X3W4V5U6T7S"],
"received_at": "2026-10-22T09:15:30.456Z",
"uplink_message": {
"f_port": 1,
"frm_payload": "ALxhTl8JKVA=",
"rx_metadata": [{
"gateway_ids": {
"gateway_id": "test"
},
"rssi": -42,
"channel_rssi": -42,
"snr": 4.2
}],
"settings": {
"data_rate": {
"lora": {
"bandwidth": 125000,
"spreading_factor": 7
}
},
"frequency": "868000000"
},
"received_at": "2026-10-22T09:15:30.123Z"
},
"simulated": true
}

Uplinks from real devices carry more fields, such as f_cnt, version_ids, and network_ids. The converter maps them to these metadata keys:

Metadata key Source in the message
deviceId, applicationId end_device_ids.device_id, end_device_ids.application_ids.application_id
eui, joinEui, devAddr end_device_ids.dev_eui, join_eui, dev_addr
fPort, fCnt uplink_message.f_port, f_cnt
data, decoded uplink_message.frm_payload (Base64 string), decoded_payload
rssi, snr rssi and snr of the gateway in uplink_message.rx_metadata with the strongest signal
rxMetadata uplink_message.rx_metadata, the full array
bandwidth, spreadingFactor, codeRate, frequency, dataRateIndex uplink_message.settings
latitude, longitude, altitude, source uplink_message.locations.user
brandId, modelId, hardwareVersion, firmwareVersion, bandId uplink_message.version_ids
netId, nsId, tenantId, clusterId, clusterAddress, tenantAddress uplink_message.network_ids
receivedAt, uplinkMessageReceivedAt, time, timestamp received_at, uplink_message.received_at, uplink_message.settings.time, settings.timestamp
receivedAtTs, uplinkMessageReceivedAtTs, timeTs The same times in milliseconds
ts uplinkMessageReceivedAtTs, else receivedAtTs, else the current server time
payloadFormat BINARY for frm_payload, JSON for decoded_payload
correlationIds, sessionKeyId, consumedAirtime, attributes, simulated The fields with the same names

A key is missing from the metadata when the message has no such field.

Test the Decoder

Click Test payload decoder below the editor. The dialog shows the Payload and the Metadata after unwrapping: a sample message for a new converter, or the last uplink once the converter has received data. To test with the message from Decoder Inputs, click the replay icon next to the payload, paste the message into Updated RAW payload, and apply it. ThingsBoard unwraps it again and fills in the payload and metadata.

Click Test. For the payload 00BC614E5F092950, the Decoder output panel shows:

{
"attributes": {
"sn": 12345678
},
"telemetry": {
"ts": 1792660530123,
"values": {
"battery": 95,
"temperature": 23.45,
"saturation": 80
}
}
}

ts comes from uplink_message.received_at. When ThingsBoard saves the data, it also adds the keys from the Telemetry and Attributes lists that the uplink has: for the message above, data, rssi, and snr as telemetry, and eui, devAddr, fPort, bandwidth, spreadingFactor, and frequency as attributes. If the output is empty or shows an error, fix the decoder and test again.

Use a Converter from the Library

The Converters Library holds ready-made uplink converters for The Things Stack Industries, for devices from vendors such as AgroSense, Bosch, Decentlab, Elsys, Lansitec, and Milesight. See Converters library.

  1. Go to Integrations ⇾ Data converters and click + Add data converter ⇾ Create new converter.
  2. Keep Uplink, and select The Things Stack Industries as the Integration type.
  3. Switch the toggle from Create new to Library.
  4. Vendor — select the manufacturer of your device, for example Milesight.
  5. Model — select the device model, for example AM102L.
  6. Name — filled in for you, for example Things Stack Industries Uplink Converter for Milesight AM102L. Change it if you like.
  7. Check the decoder and the Advanced decoding parameters, then click Add.

You can also take a library converter in the integration wizard: click Library in the Uplink data converter step.

A library converter can be built in one of two ways, so check which one you got:

  • Typed, like the converter above: the function is payloadDecoder(payload, metadata), the form has Device name and the full Advanced decoding parameters, and the test button is Test payload decoder. The decoder gets the unwrapped device payload.
  • Generic: the function is decoder(payload, metadata), Advanced decoding parameters has only the Update only keys list, and the test button is Test decoder function. The decoder gets the whole The Things Stack message and parses it itself. It also sets the device name and profile itself, for example AM102L thermostat-a with the profile AM102L for the Milesight AM102L. Most library converters for The Things Stack Industries are of this kind.
  1. Go to Integrations ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Integration type — select The Things Stack Industries.
    • Name — keep the default The Things Stack Industries integration or enter your own.
    • 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 TTI Uplink Converter.
    • Alternatively, click Create new to write a decoder here, or Library to take one from the Converters Library.
    • Click Next.
  4. Downlink data converter:
    • Click Skip. Add a downlink converter later if you need to send commands.
  5. Connection:
    • Host type — keep Region.
    • Region — the part of the Public TLS address before .cloud.thethings.industries, for example thingsboard-test.eu1. ThingsBoard appends .cloud.thethings.industries. If your tenant has another address, select Custom as the Host type and enter the full host in Custom host.
    • Port — keep 8883.
    • Credentials — paste the MQTT Username, for example my-thingsboard@thingsboard-test, and the API key as the Password.
    • Enable SSL — keep it on.
    • Topic filters — keep v3/+/devices/+/up.
    • Leave the other parameters at their defaults. See Connection Settings for details.
  6. Optionally, click Check connection. The wizard shows Connected when ThingsBoard can sign in to the MQTT server.
  7. Click Add.

The integration connects to the MQTT server right away and subscribes to the topic filters.

Parameter Default Description
Host type Region Region builds the host from the Region field. Custom takes the full host from Custom host, for an Enterprise deployment on your own domain.
Region — For Region. The part of the host before .cloud.thethings.industries, for example thingsboard-test.eu1. Required. Must be a public address on ThingsBoard Cloud.
Custom host — For Custom. The full host name of the MQTT server, without the port. Required.
Port 8883 Port of the MQTT server, from 1 to 65535. 8883 is MQTT over TLS. Use 1883 only with Enable SSL off.
Username and Password — In Credentials. The MQTT username of the application, {applicationId}@{tenantId}, and an API key. Only this credentials type is offered, and both values are required.
Enable SSL On Connects over TLS and checks the server certificate against the trusted certificates of the ThingsBoard server. No client certificate is sent.
Topic filters v3/+/devices/+/up, QoS At most once Topics to subscribe to. + matches one topic level, so the default receives the uplinks of every device the credentials can access. Subscribe only to .../up topics: the converter expects an uplink_message in every message.
Execute remotely Off Runs the integration as a separate process outside the ThingsBoard cluster, for an MQTT server in a private network. ThingsBoard generates an Integration key and Integration secret for it. See Remote Integration.
Protocol version MQTT 3.1.1 In Advanced settings. MQTT 5 is not offered for this integration.
Max bytes in message 32368 In Advanced settings. Maximum size of a received MQTT message, from 1 to 256000000 bytes.
Connection timeout (sec) 10 In Advanced settings. How long ThingsBoard waits for the MQTT server to accept the connection, from 1 to 200 seconds.
Description — In Advanced settings. Free-text description.
Metadata — In Advanced settings. Key–value pairs added to the metadata of every message from this integration.
Downlink topic pattern v3/{username}/devices/${devId}/down/push In Advanced settings. Read-only. ThingsBoard fills in the Username and replaces ${devId} with the devId value from the downlink converter result.

ThingsBoard always connects with a clean session and a generated client ID.

Simulate an uplink in The Things Stack Console, then confirm that ThingsBoard decoded it and created the device.

  1. In the Console, go to End devices in your application and open thermostat-a.
  2. Open the Messaging tab and select Simulate uplink.
  3. FPort — keep 1.
  4. Payload — enter 00BC614E5F092950.
  5. Click Simulate uplink. The Console confirms that the uplink was sent.

The payload holds sn = 12345678, battery = 95, temperature = 23.45, and saturation = 80 in the byte layout of the default decoder.

  • Integration events — go to Integrations ⇾ Integrations, open the integration, and click the Events tab. The uplink appears as an event of type Uplink with status OK. Click ⋅⋅⋅ in the Message column to see the topic and the message.
  • Converter events — open TTI Uplink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the full The Things Stack message, before unwrapping. Out shows the decoder result. Metadata shows integrationName and topic.
  • Device — go to Devices & assets ⇾ Devices. The integration has created the device Device 70B3D57ED80054FE, named after your DevEUI, with the profile my-thingsboard and the label thermostat-a. Open it and check:
    • Latest telemetry — battery, temperature, and saturation from the decoder, and data, rssi, and snr from the message.
    • Attributes — sn from the decoder, and eui, devAddr, fPort, and the radio settings in Client attributes.

ThingsBoard publishes each downlink right away to the MQTT server, with QoS 1. Nothing is queued in ThingsBoard. The Things Stack adds the downlink to the queue of the device and sends it in the next receive window. A Class A device has one after each uplink.

The downlink converter turns a Rule Engine message into a The Things Stack downlink message and returns the end device ID for the topic. In this guide, a new shared attribute is sent to the device as JSON on the frame port of its last uplink. For the full encoder reference, see Downlink data converter.

  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 The Things Stack Industries integration type are preselected.
  3. Enter a name, for example TTI Downlink Converter.
  4. Main encoding configuration opens in TBEL with a generic encoder. It builds a JSON object from temperatureUploadFrequency and humidityUploadFrequency and sets an MQTT topic, not the downlinks array and devId that The Things Stack needs. Replace it with the encoder below. For JavaScript, use the TBEL / JS toggle and the JavaScript tab.
  5. To record downlink events, click the debug button next to the name, select All messages, and click Apply.
  6. Click Add.
  7. Click Apply changes.

Encoder used in this guide. It sends the whole message as JSON, Base64-encoded in frm_payload, on the frame port from the fPort client attribute of the device:

/** Encoder **/
// End device ID. The rule chain adds it to the metadata as devId.
var devId = metadata.devId;
if (devId == null || devId == "") {
raiseError("Missing required metadata field: devId");
}
// Frame port of the last uplink. The rule chain adds the fPort client attribute as cs_fPort.
if (metadata.cs_fPort == null) {
raiseError("Missing required metadata field: cs_fPort");
}
var fPort = parseInt("" + metadata.cs_fPort);
if (fPort < 1 || fPort > 223) {
raiseError("Invalid LoRaWAN fPort. Expected a value from 1 to 223.");
}
// The message as JSON, for example {"powerState":"on"}, encoded as Base64.
var frmPayload = bytesToBase64(stringToBytes(JSON.stringify(msg)));
var data = {
downlinks: [{
f_port: fPort,
frm_payload: frmPayload,
confirmed: false,
priority: "NORMAL"
}]
};
return {
contentType: "JSON",
data: JSON.stringify(data),
metadata: {
// Replaces ${devId} in the downlink topic pattern.
devId: devId
}
};

To check the encoder, click Test encoder function. Replace the Message with {"powerState": "on"}, add devId = thermostat-a and cs_fPort = 1 to Metadata, and click Test. The Output panel shows:

{
"contentType": "JSON",
"data": "{\"downlinks\":[{\"f_port\":1,\"frm_payload\":\"eyJwb3dlclN0YXRlIjoib24ifQ==\",\"confirmed\":false,\"priority\":\"NORMAL\"}]}",
"metadata": {
"devId": "thermostat-a"
}
}

The integration reads these fields from the encoder result:

Field Required Description
contentType Yes JSON, TEXT, or BINARY. With JSON and TEXT, data is published as UTF-8 text. With BINARY, data must be Base64 and is published as the decoded bytes.
data Yes The message published to The Things Stack. It must hold a downlinks array, each entry with f_port and frm_payload (Base64), and optionally confirmed and priority. See MQTT Server in The Things Stack documentation. A result with empty data is skipped.
metadata.devId Yes The end device ID. ThingsBoard replaces ${devId} in the Downlink topic pattern with it, and replaces any other ${key} with the value of metadata.key.

To adapt:

  • Send only some keys — replace JSON.stringify(msg) with JSON.stringify({ powerState: msg.powerState }).
  • Binary command — build the bytes yourself and pass them to bytesToBase64() in TBEL, or btoa() in JavaScript.
  • Confirmed downlink — set confirmed: true to ask the device for an acknowledgment. The Things Stack retries the downlink until the device acknowledges it, which can delay later downlinks.
  • Fixed port — replace the cs_fPort lookup with a number, for example var fPort = 2;.

The encoder needs the end device ID and the frame port. The uplink converter stores the end device ID as the device label and fPort as a client attribute. Add both to the metadata, then pass the message to the integration.

  1. Go to Data processing ⇾ Rule chains and open the Root Rule Chain.
  2. From the Enrichment section, drag an originator attributes node onto the canvas:
    • Name — for example Add fPort.
    • Client attributes — fPort. The node adds it to the metadata as cs_fPort.
    • Add originator attributes to — keep Metadata.
    • Click Add.
  3. From the Enrichment section, drag an originator fields node onto the canvas:
    • Name — for example Add Device ID.
    • Under Originator fields mapping, set Source field to Label and Target key to devId.
    • Add mapped originator fields to — keep Metadata.
    • Click Add.
  4. From the Action section, drag an integration downlink node onto the canvas:
    • Name — for example Downlink to TTI.
    • Integration — select The Things Stack Industries integration.
    • Click Add.
  5. Connect the message type switch node to Add fPort with the Attributes Updated relation.
  6. Connect Add fPort to Add Device ID, and Add Device ID to Downlink to TTI, with the Success relation.
  7. Click Apply changes.
  1. Go to Devices & assets ⇾ Devices and open the device created in Test Uplink.
  2. On the Attributes tab, select Shared attributes and click +.
  3. Enter Key powerState, keep the String type, enter Value on, and click Add.
  • Converter events — open TTI Downlink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the message {"powerState": "on"} with cs_fPort and devId in its metadata. Out shows the downlinks array and devId.
  • Integration events — open the integration’s Events tab. Two events of status OK appear: Downlink: ATTRIBUTES_UPDATED for the message from the Rule Engine, and Downlink for the published message, with the topic, for example v3/my-thingsboard@thingsboard-test/devices/thermostat-a/down/push, and the payload.
  • The Things Stack — open the end device in the Console and click Live data. The downlink appears as a Receive downlink data message event. A real Class A device gets it after its next uplink.
Symptom Cause Fix
Check connection fails, or no events at all The host is wrong: the Region does not match the Public TLS address of the tenant. Enter the part of the Public TLS address before .cloud.thethings.industries, for example thingsboard-test.eu1, or select Custom and enter the full host.
Failed to connect to MQTT broker at ... with a result code The Username or Password is wrong, or the API key was deleted or lacks the rights of the MQTT integration. Copy the Username from Other integrations ⇾ MQTT again, in the form {applicationId}@{tenantId}. Generate a new API key and paste it as the Password.
Connection timeout Port and Enable SSL do not match, or a firewall blocks the port. Use 8883 with Enable SSL on. Allow outbound TCP to the port.
Host must be in the public network., or Usage of local network host for MQTT broker connection is not allowed! The host is a private address, and the platform allows only public hosts. Use the public address, or run the integration as a Remote Integration.
Connected, but no Uplink events No uplinks arrive in the application, the topic filter was changed, or debug mode is off. Check Live data of the end device in the Console. Keep the topic filter v3/+/devices/+/up. Turn debug mode on again.
Uplink events with status ERROR for messages that are not uplinks A topic filter such as v3/+/devices/+/# also receives join, downlink, and other events, which have no uplink_message. Subscribe only to .../up topics.
Converter error Payload formatter output does not contain a 'bytes' field. The application or device has a payload formatter, so the decoder gets its JSON output, not bytes. Remove the formatter in The Things Stack, or read the values from parsed in the decoder.
Wrong values, or an error about the payload length The byte offsets in the decoder do not match the device payload. Compare the data value in the converter In with the offsets in parseBytesToInt().
Device not created Allow create devices or assets is off, or the device name resolves to an empty value. Turn the option on. Check Device name in the converter and the metadata in the test dialog.
Device named Device $eui The message has no end_device_ids.dev_eui, so $eui stays unresolved. Use another key in Device name, for example $deviceId.
Attributes such as eui do not change on later uplinks Expected: keys in the Update only keys list are stored only when the value changes. Remove a key from the list to store it with every uplink.
No downlink and no error No downlink converter is assigned, or the rule chain does not route attribute updates. Assign the converter and check the Attributes Updated relation.
Downlink error Missing required metadata field: devId The device has no label, or the originator fields node is missing. Keep Device label $deviceId in the uplink converter, or set the label of the device to the end device ID. Check the Add Device ID node.
Downlink error Missing required metadata field: cs_fPort The device has no fPort client attribute yet, or the originator attributes node is missing. Send an uplink first. Check the Add fPort node.
Downlink event is OK, but nothing in Live data The topic does not match the end device: the label is not the end device ID, or the username in the Downlink topic pattern is not the application’s. Compare the topic in the integration event with the application ID, tenant ID, and end device ID in the Console.
Downlink in Live data, but the device does not react A Class A device receives a downlink only after its next uplink. A confirmed downlink is retried until the device acknowledges it. Wait for the next uplink. Use confirmed: false unless you need an acknowledgment.

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.