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

KPN Things Integration

KPN Things Integration receives device data from KPN Things, the IoT platform of the Dutch operator KPN, through a ThingsBoard destination in a KPN Things Flow. An uplink data converter transforms each message into device data, including telemetry and attributes. For downlink, ThingsBoard sends commands to the device through the KPN Things API.

Use KPN Things Integration when:

  • Your devices connect through KPN Things, over LoRa, LTE-M, or mobile data, and KPN Things already decodes their data.
  • You need to send commands from ThingsBoard to those devices, for example when a shared attribute changes.
  1. Receive data. The device sends data to KPN Things. The Flow decodes it and its ThingsBoard destination sends it as an HTTP request with a JSON body to the integration endpoint.
  2. Check the request (optional). If you set a destination shared secret or a headers filter, the integration rejects requests that fail the check with 403 Forbidden.
  3. Decode the payload. The uplink converter returns the device name, telemetry, and attributes. If Allow create devices or assets is on, ThingsBoard creates the device on its first message.
  4. Send a command (optional). The Rule Engine passes a message to the integration. The downlink converter encodes it, and ThingsBoard sends it right away to POST https://api.kpnthings.com/api/actuator/downlinks?port={FPort}.
  • Access to ThingsBoard Cloud with integrations enabled for your tenant. The ThingsBoard endpoint must be reachable from the internet, because KPN Things calls it.
  • Permission to create integrations and data converters, and to edit rule chains for downlink.
  • A KPN Things portal account.
  • For downlink: access to the KPN Zakelijk portal to create an API key.

In KPN Things, a device sends data only through a Flow. The Flow decodes the data and passes it to its destinations. This guide uses the KPN Device Simulator as the device, so you can test the integration without hardware.

Here you create the device, link it to a Flow, and turn on decoding. The ThingsBoard destination comes later: it needs the integration endpoint, so you add it after creating the integration.

Add a Device Simulator (Web app) device to your project. The Web app runs in a browser on your computer or phone and sends the measurements you select when you click a button.

  1. In the KPN Things portal, open Things Manager and click My first project.
  2. In the Devices row, click Add Device.
  3. Under KPN Things offered Device Types, select Device Simulator (Web app).
  4. Enter a Name, for example My KPN Device, and click Add Device.
  5. The device page opens. Device type is Device Simulator (Web app), and Processing shows Not yet linked to Flow until you link the device to a Flow.

Link the device to a Flow, so its data reaches the Flow’s decoder and destinations. If your project has no Flow yet, create one first.

  1. Create a Flow. In the left menu, next to Processing, click + (Add Flow). Enter a Flow name, for example My first flow, and click Create Flow. The Flow page opens with the message Your Flow was created. If the project already has a Flow, open it from Flows in the left menu instead.
  2. In the Devices row of the Flow, click Link Device.
  3. Click Link next to My KPN Device. The message The Device has been successfully linked to the Flow appears, and the device is listed in Devices in My first flow.

The decoder in the Flow turns the device data into named values. Without it, ThingsBoard receives raw SenML records.

  1. In the Devices in My first flow list, click My KPN Device.
  2. Open the Flows tab. It shows the Flow as a diagram: the device, Decoders, Encoders, and destinations.
  3. In Decoders, turn on Decoded ThingsML and raw SenML data. The change is saved automatically. Leave the SenML data encoder in Encoders on: it is on by default, and downlink needs it.

Create the uplink converter and the integration, then point a KPN Things destination at the integration endpoint.

The uplink converter receives the request body as a byte array and returns the device data. KPN Things 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.

The ThingsBoard destination sends the data already in the converter output format (see Decoder Inputs), so the default decoder returns the body unchanged.

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

  2. Converter type — keep Uplink.

  3. Integration type — select KPN Things.

  4. Name — enter a name, for example KPN Things Uplink Converter.

  5. Main decoding configuration — the TBEL editor opens with the KPN Things decoder below. Keep it. The TBEL / JS toggle switches to a generic JavaScript template that does not read the KPN Things body: if you use JavaScript, replace it with the decoder on the JavaScript tab.

    /*
    By default, we receive a message that is already correctly formatted.
    But you can change the code for your purposes.
    */
    return decodeToJson(payload);

    To adapt:

    • Device name — the destination sends the KPN Things device URN as deviceName. Set data.deviceName to another value, for example data.deviceLabel, to use a readable name. Downlink needs the URN, so store it as an attribute if you change the name.
    • Device profile — deviceType holds the KPN Things device type, for example Device Simulator (Web app). Set it to the name of the device profile you want.
    • Attributes — add an attributes object, for example data.attributes = { kpnLabel: data.deviceLabel };.
    • Group or customer — add groupName or customerName to the result.
    • Update-only keys — for KPN Things, ThingsBoard pre-fills the Update only keys list in Advanced decoding parameters with battery, DVNUUID, and DEVEUI. These keys are stored only when their value changes. Edit the list to match your keys.
  6. Click Test decoder function and check the result (see Test the Decoder).

  7. Click Add.

Decoder Inputs

Variable Type Content
payload byte array The request body sent by the ThingsBoard destination.
metadata {[key: string]: string} integrationName, every request header as Header:<name> with the name in lowercase, and the key–value pairs from the integration’s Metadata field. The ThingsBoard destination sends Header:x-things-secret, Header:things-message-token, Header:things-client-id, and Header:things-plug-uuid, among others.

With Decoded ThingsML and raw SenML data on, the body looks like this:

{
"deviceName": "urn:dev:DVNUUID:6776c443-8b0a-42fe-b8ca-d8a1cf880492:",
"deviceLabel": "My KPN Device",
"deviceType": "Device Simulator (Web app)",
"telemetry": [{
"ts": 1792571305000,
"values": {
"battery": "87",
"temperature": 23.6,
"orientation": "0,0,0,0",
"latitude": 51.9067285,
"longitude": 4.490617
}
}]
}
  • deviceName — the device URN in the form urn:dev:DVNUUID:{UUID}:. It stays the same for the lifetime of the device in KPN Things.
  • deviceLabel — the device name in KPN Things. ThingsBoard stores it as the device label.
  • deviceType — the device profile name. Without it, ThingsBoard uses the default profile.
  • telemetry — one or more records with a timestamp ts in milliseconds and the decoded values. Numeric strings such as "87" are stored as numbers.

Test the Decoder

Click Test decoder function below the editor. The dialog opens with a generic sample payload, with Payload content type set to JSON. Replace the payload with the body from Decoder Inputs and click Test. The Output panel shows the same object, because the default decoder returns the body unchanged:

{
"deviceName": "urn:dev:DVNUUID:6776c443-8b0a-42fe-b8ca-d8a1cf880492:",
"deviceLabel": "My KPN Device",
"deviceType": "Device Simulator (Web app)",
"telemetry": [{
"ts": 1792571305000,
"values": {
"battery": "87",
"temperature": 23.6,
"orientation": "0,0,0,0",
"latitude": 51.9067285,
"longitude": 4.490617
}
}]
}

Check that deviceName holds the URN and telemetry holds the expected keys. If the output is empty or shows an error, fix the decoder and test again.

  1. Go to Integrations ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Integration type — select KPN Things.
    • Name — keep the default KPN Things integration or enter your own.
    • Enable integration and Allow create devices or assets — keep both on, so the device is created on its first message.
    • Click Next.
  3. Uplink data converter:
    • Click Select existing and choose KPN Things Uplink Converter.
    • Alternatively, click Create new to write a decoder here.
    • Click Next.
  4. Downlink data converter:
    • Click Skip. Add a downlink converter later if you need to send commands.
  5. Connection:
    • Copy the HTTP endpoint URL. You need it for the KPN Things destination.
    • Leave the other parameters at their defaults. See Connection Settings for details.
  6. Click Add.
Parameter Default Description
Base URL Address of the ThingsBoard server you are signed in to, for example https://thingsboard.cloud Used to build the endpoint URL. Must be a public address. Required.
Destination shared secret — If set, every request must carry a Things-Message-Token header with the SHA-256 hash (hex) of the request body followed by this secret. Leave it empty for the ThingsBoard destination: it signs with a secret that KPN Things does not show. See Secure the Endpoint.
HTTP endpoint URL — Read-only. Format: {Base URL}/api/v1/integrations/kpn/{integrationKey}, where integrationKey is a UUID assigned at creation. Accepts JSON bodies only.
Allow downlink Off Shows the Credentials fields. See Configure Downlink.
API ID and API Key — In Allow downlink ⇾ Credentials. ID and secret key of a KPN API key. ThingsBoard exchanges them for an access token. Required when Allow downlink is on.
Enable security (Headers filter) Off Accepts only requests that carry every listed Header with the exact Value. See Secure the Endpoint.
Execute remotely Off Runs the integration as a separate process outside the ThingsBoard cluster. ThingsBoard generates an Integration key and Integration secret for it. KPN Things needs a public endpoint, so the standard setup keeps this off. See Remote Integration.
Description — In Advanced settings. Free-text description.
Metadata — In Advanced settings. Key–value pairs added to the metadata of every message from this integration.

The integration answers 200 OK when the converter returned data, 204 No Content when it returned nothing, 400 Bad Request on a converter script error, and 403 Forbidden when the security check fails.

A destination tells the Flow where to send device data. Create it from the device’s flow diagram, and KPN Things links it to the Flow.

  1. On the Flows tab of My KPN Device, click Connect destination in the No destinations connected block.
  2. The Choose a Destination to link page lists the destinations of the project. Click + Add new Destination.
  3. Find ThingsBoard and click Choose ThingsBoard.
  4. Enter a Destination Name, for example ThingsBoard.
  5. Under Connection Details:
    • HTTP endpoint URL — paste the HTTP endpoint URL of the integration.
    • Security Header — the Header is pre-filled with X-Things-Secret. Click Generate to create the Value, or enter your own token. Copy the value for Secure the Endpoint. ThingsBoard checks this header only after you turn on the headers filter there. Until then, it accepts requests with any header value or none.
  6. Click Add ThingsBoard Destination. The destination page opens with the message The Destination has been successfully linked to the Flow. Processing is Active, and Flows shows My first flow.
  7. Open the Flows tab of My KPN Device again. The flow diagram shows the device, the decoder, and the active ThingsBoard destination.

Anyone who knows the endpoint URL can send data to it. Check the X-Things-Secret header that the destination sends: the integration then rejects every request without the right value with 403 Forbidden, before the converter runs.

  1. In ThingsBoard, open the integration and click Toggle edit mode (pencil icon).
  2. Turn on Enable security (Headers filter).
  3. Click Add. Enter X-Things-Secret as the Header and paste the generated value as the Value. A request must carry every header in the list. The value match is exact and case-sensitive.
  4. Click Apply changes.

If you click Generate in the destination again, update the value in ThingsBoard too.

Every KPN Things destination also sends a Things-Message-Token header: the SHA-256 hash of the body followed by a shared secret. The ThingsBoard destination signs with a secret that KPN Things does not show, so leave Destination shared secret empty and use the headers filter. Destination shared secret is for destinations where you set the secret yourself, such as the generic HTTPS destination. ThingsBoard hashes the JSON body in compact form, without extra spaces or line breaks.

Send data from the Device Simulator, then confirm that ThingsBoard decoded it and created the device.

The Device Simulator is a web app that sends data as the KPN Things device.

  1. In the KPN Things portal, open My KPN Device and go to the Application tab.
  2. Under Open the application, click Open the Device simulator application in a new tab.
  3. Under Select data to send, select the data, for example Battery level, Temperature, and Location, and adjust the values if needed.
  4. Click Send data now. The Simulated device data updated successfully message appears.
  • Integration events — go to Integrations ⇾ Integrations, open the integration, and click the Events tab. The message appears as an event of type Uplink with status OK. Click ⋅⋅⋅ in the Message column to see the body.
  • Converter events — open KPN Things Uplink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the body, Out shows the decoded result, and Metadata shows the integration name and the request headers, such as Header:x-things-secret.
  • Device — go to Devices & assets ⇾ Devices. The integration has created a device named after the URN, for example urn:dev:DVNUUID:6776c443-8b0a-42fe-b8ca-d8a1cf880492:, with the Device Simulator (Web app) profile and the label My KPN Device. Open it and check the values on the Latest telemetry tab: battery, temperature, orientation, latitude, and longitude.

ThingsBoard sends each downlink right away as a KPN Things API call. Nothing is queued in ThingsBoard: if the call fails, ThingsBoard records an error and drops the command.

For each downlink, the integration:

  1. Gets an access token from KPN with the API ID and API Key, and reuses it until 10 minutes before it expires.
  2. Sends the data of the encoder result to POST https://api.kpnthings.com/api/actuator/downlinks?port={FPort} as application/json, with the token as a Bearer token.

The downlink converter turns a Rule Engine message into that body. For the full encoder reference, see Downlink data converter.

The integration authenticates to the KPN Things API with an API key of your KPN organization.

  1. Sign in to the KPN Zakelijk portal and click API keys in the left menu.
  2. Click Add API key.
  3. Enter a Display name, for example ThingsBoard, and click Add API key.
  4. The General tab of the new key opens. Check that Activate API Key is on, and copy the ID and the Secret key. Click the eye icon to show the secret key.
  5. Open the Services and roles tab and click Add service.
  6. Select KPN Things, then select the Things Manager - Editor role, and click Add. Select one role per service: if you select several, the lowest one applies.
  7. KPN Things is listed with the status Added. Click Save changes.

Add a downlink converter to the integration and turn on Allow downlink with the API key.

  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 KPN Things integration type are preselected.
  3. Enter a name, for example KPN Things 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 SenML records and FPort that KPN Things 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. Debug is off by default.
  6. Click Add.
  7. Enable downlink: turn on Allow downlink. Under Credentials, paste the ID into API ID and the Secret key into API Key.
  8. Click Apply changes.

Encoder used in this guide. It turns every key of the message into a SenML record, so it sends any shared attribute that the rule chain passes: numbers as v, booleans as vb, and other values as vs. A message with no keys produces no downlink.

/** Encoder **/
// KPN Things device URN. The rule chain adds it to the metadata as deviceName.
var deviceUrn = metadata['deviceName'];
// One SenML record per key of the message, for example {"temperature": 25}.
var senmlPack = [];
foreach (element : msg.entrySet()) {
var value = element.value;
var record = { "bn": deviceUrn, "n": element.key };
if (value instanceof Boolean) {
record.vb = value;
} else if (value instanceof Number) {
record.v = value;
} else {
record.vs = "" + value;
}
senmlPack.add(record);
}
// Nothing to send.
if (senmlPack.size() == 0) {
return [];
}
return {
contentType: "JSON",
data: JSON.stringify(senmlPack),
metadata: {
// Port sent as the "port" query parameter. Required.
// For LoRaWAN devices, use the port your device listens on. The simulator accepts any port.
FPort: 1
}
};

To check the encoder, click Test encoder function. Replace the Message with {"temperature": 25, "mode": "eco", "enabled": true} and click Test. The Output panel shows one SenML record per key, with bn set to the deviceName value from Metadata:

{
"contentType": "JSON",
"data": "[{\"bn\":\"sensorA\",\"n\":\"temperature\",\"v\":25},{\"bn\":\"sensorA\",\"n\":\"mode\",\"vs\":\"eco\"},{\"bn\":\"sensorA\",\"n\":\"enabled\",\"vb\":true}]",
"metadata": {
"FPort": 1
}
}

With an empty message {}, the output is [], and nothing is sent.

The integration reads these fields from the encoder result:

Field Required Description
data Yes Request body sent to KPN Things as is. Use a SenML array whose base name bn is the device URN.
contentType Yes JSON or TEXT. The body is always sent as application/json.
metadata.FPort Yes Port sent as the port query parameter. For LoRaWAN devices, the LoRaWAN port. Without it, the downlink fails with Cannot find FPort in metadata!. The integration also reads FPort from the Rule Engine message metadata and from the integration’s Metadata field.
metadata.subCustomerId No ID of a KPN sub-customer that owns the device. ThingsBoard requests access to the sub-customer once and sends the ID as the x-client-id header.

To send only some keys, wrap the body of the loop in a condition, for example if (element.key == "temperature") { ... }. To send several downlinks from one message, return an array of results.

The encoder needs the device URN. Add it to the metadata with an originator fields node, 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 fields node onto the canvas:
    • Name — for example Add Device Name.
    • Under Originator fields mapping, set Source field to Name and Target key to deviceName.
    • Add mapped originator fields to — keep Metadata.
    • Click Add.
  3. From the Action section, drag an integration downlink node onto the canvas:
    • Name — for example Downlink to KPN Things.
    • Integration — select KPN Things integration.
    • Click Add.
  4. Connect the message type switch node to Add Device Name with the Attributes Updated relation.
  5. Connect Add Device Name to Downlink to KPN Things with the Success relation.
  6. 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 temperatureUploadFrequency, select the Integer type, enter Value 60, and click Add.
  • Converter events — open KPN Things Downlink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the message {"temperatureUploadFrequency": 60} with the device URN as deviceName in its metadata. Out shows the SenML data and FPort.
  • 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 call to KPN Things, with the SenML payload and FPort in its message. A failed call appears with an error and the KPN Things response.
  • KPN Things — open the device in Things Manager ⇾ Devices, click the Send instruction tab, and scroll to Status Downlink. Click Refresh if the list is empty. The TemperatureUploadFrequency: 60 entry shows that KPN Things accepted the downlink. Its status is PENDING or EXECUTING. KPN Things sets it, not ThingsBoard.
Symptom Cause Fix
No events on the integration Events tab The device or the destination is not linked to the Flow, the endpoint URL is wrong, or the integration is disabled. Or debug mode is off: it records events for 15 minutes after you turn it on. Check that the device’s Flows tab shows the device, the decoder, and the active destination. Copy the HTTP endpoint URL again. Turn on Enable integration. Turn debug mode on again.
Uplink events with status FORBIDDEN, and no converter events The X-Things-Secret value does not match the Headers filter. Copy the value from the destination again. If you clicked Generate again, update the value in ThingsBoard.
Same, with Destination shared secret set The ThingsBoard destination signs the body with a secret that KPN Things does not show, so the Things-Message-Token hash never matches. Clear Destination shared secret and use the headers filter.
Uplink events with status ERROR The decoder failed. Check the Error column in the converter events and fix the decoder.
Telemetry keys such as n, u, or bn Decoded ThingsML and raw SenML data is off. Turn it on in the device’s Flows tab.
Device not created Allow create devices or assets is off, or the decoder returns no deviceName. Turn the option on. Check Out in the converter events.
Telemetry keys such as telemetry.0.values.battery, or a device named Unknown Device The JavaScript decoder is the generic template, which does not read the KPN Things body. Use the TBEL decoder, or replace the JavaScript template with the decoder from this guide.
No downlink and no error No downlink converter is assigned, the rule chain does not route attribute updates, or the encoder returned [] because the message had no keys. Assign the converter and check the Attributes Updated relation. Check Out in the downlink converter events.
Downlink sent, but bn is empty or not the device URN The originator fields node is missing, or it adds the name to the message instead of the metadata. Connect Add Device Name between the message type switch and the integration downlink node, with Add mapped originator fields to set to Metadata.
Cannot find FPort in metadata! The encoder does not set metadata.FPort. Use the encoder from this guide, or add FPort to the integration’s Metadata.
Downlink ERROR with 400 Bad Request on POST request for "https://auth.grip-on-it.com/api/v3/idp/oidc/token", for example Feature API Key does not exist anymore. The API ID or API Key is wrong, or the key was deleted or deactivated. Copy the ID and Secret key again, and check that Activate API Key is on. A changed key takes effect only after the cached access token expires, up to 50 minutes later. To apply it right away, turn Enable integration off and on again.
Downlink fails with 403 The API key lacks a KPN Things role, or it has several roles in KPN Things and the lowest one applies. Under Services and roles, give the key one role in KPN Things: Things Manager - Editor or Things Manager - Admin.
Downlink fails with 400 The body is not a SenML array, or bn is not the device URN. Check Out in the converter events. Keep the device name equal to the URN, or read the URN from an attribute.

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.