APIs Device to Cloud Lorawan Devices Send and receive IoT data

Overview

This page describes how to exchange data between the Device to Cloud platform and your LoRaWAN devices.

  • Downlink (platform → device): Send a message to a device by creating a content instance in the device’s outgoing-msg container. The payload is a hex-encoded byte string. LoRaWAN-specific options (port, priority, confirmed) are set via labels.
  • Uplink (device → platform): When a device sends a LoRaWAN uplink frame, LORIOT forwards it to D2C. The platform stores the full notification payload in the device’s received-msg container.
  • Error handling: If a downlink or provisioning operation fails, the platform records error details in the error-msg and logs containers.

Send message to IoT device

To send a downlink message to a LoRaWAN device, create a content instance (ty=4) in the device’s outgoing-msg container. The con field contains the message payload as a hex-encoded byte string. Use lbl to specify the LoRaWAN port, priority, and whether the delivery should be confirmed.

  • Request
  • Response
POST {{API_URL}}/device-communication/myLoriot-Device01/outgoing-msg
Accept: application/json
Content-Type: application/json;ty=4
X-M2M-Origin: CmyApplication
X-M2M-RI: 123
Authorization: Bearer {{ACCESS_TOKEN}}

{
  "m2m:cin": {
    "con": "7123ABC",
    "lbl": ["port:100", "priority:0", "confirmed:false"]
  }
}
HTTP/2 201 Created
date: Fri, 22 May 2026 08:55:26 GMT
content-type: application/json; charset=utf-8
request-context: appId=cid-v1:
x-service-responder: device-management-orchestrator
x-m2m-ri: 123
x-m2m-rvi: 4
x-m2m-ot: 2026-05-22T08:55:26.304Z
x-m2m-rsc: 2001
x-azure-ref: 20260522T085526Z-157794674c588bv2hC1FRAqubc0000000yng00000000nr1d
x-cache: CONFIG_NOCACHE
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0
referrer-policy: no-referrer
x-tardis-traceid: e02c1daad6529714d14a233132313436
vary: Origin
x-kong-upstream-latency: 138
x-kong-proxy-latency: 2
x-kong-request-id: c124506370a5fa4ad225a547eea42631
strict-transport-security: max-age=31536000; includeSubDomains
content-length: 994
x-http2-stream-id: 3

{
  "m2m:cin": {
    "rn": "<resourceName>",
    "ri": "<resourceID>",
    "ct": "<creationTime>",
    "lt": "<lastModifiedTime>",
    "con": "7123ABC",
    "lbl": ["port:100", "priority:0", "confirmed:false"]
  }
}
LabelRequiredDescription
port:<number>YesLoRaWAN fPort to use for the downlink frame. Valid range: 1–223.
priority:<number>NoDelivery priority. 0 = normal; 1 = immediate.
confirmed:<true|false>NoWhether the LoRaWAN downlink should be a confirmed frame. false = unconfirmed; true = confirmed.
Note:
The port label is mandatory. The priority and confirmed labels are optional and fall back to their default values (priority:0, confirmed:false) when omitted.

The downlink is delivered to the LORIOT network server as a downlink data message with the following parameters:

ParameterTypeRequiredDescription
cmdstringYesCommand type. Must always have the value tx.
EUIstringYesDevice EUI — 16 hex digits (without dashes).
portnumberYesLoRaWAN fPort to use for the downlink frame. Valid range: 1–223.
datastringNoData payload (decrypted; plaintext hex string to be encrypted on the Network Server). Only present if an APPSKEY is assigned to the device; if no APPSKEY is assigned to the device, an error is returned.
prioritynumberNoDelivery priority. 0 = normal; 1 = immediate.
confirmedbooleanNoWhether the LoRaWAN downlink should be a confirmed frame. false = unconfirmed; true = confirmed.

For more details, see the LORIOT Downlink Data Message documentation.

Note:

When you create the content instance, the platform builds the downlink data message for you:

  • data is taken from the con field, which must be a hex-encoded byte string (e.g. "7123ABC").
  • port, priority, and confirmed are taken from the lbl labels (port:<number>, priority:<number>, confirmed:<true|false>).
  • cmd (tx) and EUI (device EUI) are set automatically by the platform.

The port label is mandatory; priority and confirmed are optional and fall back to their default values (priority:0, confirmed:false) when omitted.

Receive data from IoT device

When a LoRaWAN device sends an uplink frame, the following happens:

  1. The device transmits a LoRa radio frame to the nearest gateway.
  2. The gateway forwards the frame to the LORIOT network server.
  3. LORIOT decodes the frame and sends the uplink notification to D2C.
  4. If devices doesn’t exist in D2C system, with the help of device-provisioning request, it will be created automatically.
  5. D2C stores the notification payload as a content instance in the device’s received-msg container.
  • Request
  • Response
GET {{API_URL}}/device-communication/myLoriot-Device01/received-msg/la
Accept: application/json
X-M2M-Origin: CmyApplication
X-M2M-RI: 123
Authorization: Bearer {{ACCESS_TOKEN}}
HTTP/1.1 200 OK
Date: Mon, 08 Jun 2026 13:08:27 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1112
Connection: close
request-context: appId=cid-v1:
x-service-responder: device-management-orchestrator
x-m2m-ri: 123
x-m2m-rvi: 4
x-m2m-ot: 2026-06-08T13:08:27.339Z
x-m2m-rsc: 2000
x-azure-ref: 20260608T130827Z-165bdc8f655j22fghC1FRA4bn800000007y0000000000nun
X-Cache: CONFIG_NOCACHE
Accept-Ranges: bytes
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 0
Referrer-Policy: no-referrer
X-Tardis-Traceid: e851568cae35a1fad2f12333373036
vary: Origin
X-Kong-Upstream-Latency: 242
X-Kong-Proxy-Latency: 2
X-Kong-Request-Id: ba30e324b5d8da42da323d46dc796b1b
Strict-Transport-Security: max-age=31536000; includeSubDomains

{
  "contentInstance": {
    "content": {
      "nodeResourceName": "647FDA000000101D",
      "nodeID": "urn:dev:deveui:647FDA000000101D",
      "time": "20250911T141556,721000",
      "messageType": "notify",
      "data": {
        "lorawan": {
          "command": "rx",
          "radioFrequency": 868100000,
          "radioRssi": -27,
          "radioSnr": 12,
          "timeOnAir": 660,
          "datarate": "SF11 BW125 4/5",
          "batteryLevel": 235,
          "networkFrameCounter": 390,
          "EUI": "647FDA000000101D",
          "timestamp": 1757600156721,
          "deviceFrameCounter": 726,
          "port": 10,
          "acknowledge": false,
          "online": true,
          "confirmed": false,
          "deviceAddress": "300DFAA5",
          "decryptedData": "0a00ff",
          "decodedData": {
            "data": {
              "raw": "0A 00 FF",
              "fPort": 10,
              "motion_event_state": "Detected"
            },
            "errors": [],
            "warnings": []
          }
        }
      },
      "status": {
        "code": 200,
        "message": "success",
        "detail": "Uplink message accepted and forwarded to received-msg container"
      },
      "uplinkProperties": "{}"
    },
    "contentInfo": "application/json:0",
    "resourceType": 4,
    "contentSize": 761,
    "stateTag": 0,
    "creator": "CNI-IPE",
    "resourceName": "8e94bc0d-41bf-4e63-9130-acd275715b1e",
    "resourceID": "6a26bec6598ac53dedc5f1c3",
    "parentID": "6a26bbb5598ac53dedc5f14b",
    "creationTime": "20260608T130822,708000",
    "lastModifiedTime": "20260608T130822,708000"
  }
}
  • Request
  • Response
GET {{API_URL}}/device-communication/myLoriot-Device01/received-msg/la
Accept: application/json
X-M2M-Origin: CmyApplication
X-M2M-RI: 123
Authorization: Bearer {{ACCESS_TOKEN}}
HTTP/1.1 200 OK
Date: Mon, 08 Jun 2026 13:32:55 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1248
Connection: close
request-context: appId=cid-v1:
x-service-responder: device-management-orchestrator
x-m2m-ri: 123
x-m2m-rvi: 4
x-m2m-ot: 2026-06-08T13:32:55.473Z
x-m2m-rsc: 2000
x-azure-ref: 20260608T133255Z-177c5f6578drnwslhC1FRAd0c8000000087g00000001xg3y
X-Cache: CONFIG_NOCACHE
Accept-Ranges: bytes
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 0
Referrer-Policy: no-referrer
X-Tardis-Traceid: 62efdfc1cfc51d9eb9002331383538
vary: Origin
X-Kong-Upstream-Latency: 202
X-Kong-Proxy-Latency: 4
X-Kong-Request-Id: 2f7bd428226bb8104e6fe259dd936366
Strict-Transport-Security: max-age=31536000; includeSubDomains

{
  "contentInstance": {
    "content": {
      "nodeResourceName": "647FDA000000101D",
      "nodeID": "urn:dev:deveui:647FDA000000101D",
      "time": "20230801T144627,375000",
      "messageType": "gateway-message",
      "data": {
        "lorawan": {
          "command": "gw",
          "radioFrequency": 868100000,
          "timeOnAir": 1319,
          "datarate": "SF12 BW125 4/5",
          "batteryLevel": 143,
          "networkFrameCounter": 3,
          "EUI": "647FDA000000101D",
          "timestamp": 1690901187375,
          "deviceFrameCounter": 2,
          "port": 214,
          "acknowledge": false,
          "gws": [
            {
              "radioRssi": -49,
              "radioSnr": 9.2,
              "timestamp": 1690901187377,
              "datetime": "2023-08-01T14:46:27.377Z"
            },
            {
              "radioRssi": -49,
              "radioSnr": 8.8,
              "timestamp": 1690901187375,
              "datetime": "2023-08-01T14:46:27.375Z"
            }
          ],
          "name": "Water meter",
          "decryptedData": "0102AABB",
          "decodedData": {
            "data": {
              "temperature": 28.15,
              "humidity": 0.32,
              "pulseCounter": 1
            },
            "errors": [],
            "warnings": []
          }
        }
      },
      "status": {
        "code": 200,
        "message": "success",
        "detail": "Uplink message accepted and forwarded to received-msg container"
      },
      "uplinkProperties": "{}"
    },
    "contentInfo": "application/json:0",
    "resourceType": 4,
    "contentSize": 897,
    "stateTag": 1,
    "creator": "CNI-IPE",
    "resourceName": "c183ee74-bb87-48a4-a948-51dc783033b0",
    "resourceID": "6a26c474598ac53dedc5f29e",
    "parentID": "6a26bbb5598ac53dedc5f14b",
    "creationTime": "20260608T133236,164000",
    "lastModifiedTime": "20260608T133236,164000"
  }
}

The con field of each received message contains the full LORIOT uplink notification:

FieldTypeDescription
cmd (command)string"rx" for devices and "gw" for gateways
EUIstring64-bit device EUI (hex)
seqnointegerLORIOT-internal sequence number
ts (timestamp)integerUnix timestamp (milliseconds) when LORIOT received the frame
fcnt (frameCounter)integerLoRaWAN uplink frame counter
portintegerLoRaWAN fPort of the frame
freq(radioFrequency)integerFrequency in Hz (e.g. 867300000 = 867.3 MHz)
rssi (radioRssi)integerReceived signal strength in dBm
snr (radioSnr)numberSignal-to-noise ratio in dB
toa (timeOnAir)integerTime on air in milliseconds
dr (datarate)stringLoRa data rate (e.g. "SF7 BW125 4/5")
ack (acknowledge)booleanWhether the device requested an acknowledgement
bat (batteryLevel)integerBattery level reported by the device (0–255; 255 = not available)
offline (online or offline)booleanWhether the device was offline when the frame was received
confirmedbooleanWhether the frame was a confirmed uplink
devaddr (deviceAddress)stringLoRaWAN device address (hex) assigned after OTAA join
datastringRaw uplink payload as a hex-encoded byte string
decoded (decodedData)objectDecoded payload if a codec is configured on the LORIOT application (optional)

Error handling

If an error occurs during downlink delivery or provisioning, D2C records details in two locations:

  • error-msg — device-level error container; contains the status and reason for the last failed operation.
  • logs — adapter-level log container inside d2c-protocol-adapter-loriot; contains structured log entries for troubleshooting.

When a downlink message cannot be delivered to the device, an error entry is created in the device’s error-msg container and logs container. The following table summarizes all possible error scenarios during downlink message processing.

HTTP StatusCategoryError MessageCauseRecommended Action
400ValidationDownlink message could not be processed. Mandatory label Port is missing.The lbl array in the ContentInstance does not contain the required port label.Add the port:<number> label to the lbl array (e.g. "port:100").
500Credential ResolutionInternal server error: unable to retrieve downlink token from Loriot Application.The platform could not resolve valid credentials to communicate with the LORIOT Network Server. Possible causes: the application was not properly provisioned, or the LORIOT API is temporarily unavailable.Verify that the device was provisioned successfully. If the issue persists, re-provision the application or contact support.
500Token GenerationInternal server error: unable to generate application access token in Loriot.The platform attempted to generate a new access token for the LORIOT application but the request failed.Retry the operation. If the error persists, verify the LORIOT account configuration and contact support.
500Delivery FailureDownlink message delivery to LORIOT Network Server failed.The LORIOT Network Server rejected the message or was unreachable. The error details include the HTTP status code returned by LORIOT.Check the error-msg container for specific LORIOT error details. Verify the device EUI, port number, and payload format.

Get last error for a device:

  • Request
  • Response
GET {{API_URL}}/device-communication/myLoriot-Device01/error-msg/la
Accept: application/json
X-M2M-Origin: CmyApplication
X-M2M-RI: 123
Authorization: Bearer {{ACCESS_TOKEN}}
HTTP/2 200 OK
date: Wed, 06 May 2026 18:39:45 GMT
content-type: application/json; charset=utf-8
request-context: appId=cid-v1:
x-service-responder: device-management-orchestrator
x-m2m-ri: 123
x-m2m-rvi: 4
x-m2m-ot: 2026-05-06T18:39:45.501Z
x-m2m-rsc: 2000
x-azure-ref: 20260506T183945Z-1698948dff4rhdk2hC1FRA1qrw0000000vx00000000062f8
x-cache: CONFIG_NOCACHE
accept-ranges: bytes
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0
referrer-policy: no-referrer
x-tardis-traceid: e73dacf181ec59495ca52336373930
vary: Origin
x-kong-upstream-latency: 241
x-kong-proxy-latency: 5
x-kong-request-id: 3325a5457c5e4b2794011e43b3cbfc5b
strict-transport-security: max-age=31536000; includeSubDomains
content-length: 629
x-http2-stream-id: 3
{
  "m2m:cin": {
    "con": {
      "nodeResourceName": "myLoriot-Device01",
      "nodeID": "urn:dev:deveui:0080000000017B1B",
      "data": "",
      "status": {
        "code": 500,
        "message": "internal server error",
        "detail": "Internal server error: subscription creation failed."
      }
    },
    "cnf": "application/json:0",
    "ty": 4,
    "cs": 604,
    "st": 3,
    "cr": "CmyApplication",
    "rn": "a2efd14b-d5d8-41e0-9c3c-74e907abfc95",
    "ri": "69b17f068006f89d59522af0",
    "pi": "69b132f78006f89d59521efa",
    "ct": "20260311T144110,154000",
    "lt": "20260311T144110,154000"
  }
}

Get adapter logs:

  • Request
  • Response
GET {{API_URL}}/d2c-protocol-adapter-loriot/logs/la
Accept: application/json
X-M2M-Origin: CmyApplication
X-M2M-RI: 123
Authorization: Bearer {{ACCESS_TOKEN}}
HTTP/2 200 OK
date: Wed, 06 May 2026 18:39:45 GMT
content-type: application/json; charset=utf-8
request-context: appId=cid-v1:
x-service-responder: device-management-orchestrator
x-m2m-ri: 123
x-m2m-rvi: 4
x-m2m-ot: 2026-05-06T18:39:45.501Z
x-m2m-rsc: 2000
x-azure-ref: 20260506T183945Z-1698948dff4rhdk2hC1FRA1qrw0000000vx00000000062f8
x-cache: CONFIG_NOCACHE
accept-ranges: bytes
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0
referrer-policy: no-referrer
x-tardis-traceid: e73dacf181ec59495ca52336373930
vary: Origin
x-kong-upstream-latency: 241
x-kong-proxy-latency: 5
x-kong-request-id: 3325a5457c5e4b2794011e43b3cbfc5b
strict-transport-security: max-age=31536000; includeSubDomains
content-length: 629
x-http2-stream-id: 3
{
  "m2m:cin": {
    "con": {
      "identifier": "urn:dev:deveui:0080000000017B1B",
      "type": "device processing failed",
      "service": "d2c-protocol-adapter-loriot",
      "data": "",
      "status": {
        "code": 500,
        "message": "internal server error",
        "detail": "Internal server error: d2c-protocol-adapter-loriot unable to delete device from Loriot."
      }
    },
    "cnf": "application/json:0",
    "ty": 4,
    "cs": 641,
    "stg": 2,
    "cr": "CmyApplication",
    "rn": "31af43c7-f111-4e5a-9694-7c66f5745f72",
    "ri": "69b17f068006f89d59522af1",
    "pi": "69b158c08006f89d595224b4",
    "ct": "20260311T144110,172000",
    "lt": "20260311T144110,172000"
  }
}

The con field of a log entry has the following structure:

FieldDescription
identifierDevice or resource identifier
typeLog entry type (e.g. provisioning, downlink)
serviceInternal adapter service that produced the entry
statusOutcome — success or an error code

Next: Forward messages to applications

In the next step, you learn how to integrate your application and use device groups to configure the data routing to your application endpoint.