Skip to main content

Subscribe to real-time data

Subscribes the connection to device data. Once the connection is subscribed, the server sends a realtime_data message for every uplink it receives, confirmed or unconfirmed. Data arrives from the devices of the application you are connected to and of applications that granted it access.

While the application has no subscribed connections, the server accumulates its data in a queue and sends it after subscription. So after reconnecting you also receive the uplinks that came while the client was disconnected.

With the "downlink_status": true flag the server also sends downlink_status messages that report the status of sent downlink frames.

Request and response: consume_req → consume_resp, then realtime_data messages.
Access: a token of any access level. The token access level does not affect the data stream.

Current ONS version
  • The downlink_status flag is not in the v0.17 description.
  • consume_resp contains the operation_id from the request.
  • The content of realtime_data has changed. New fields: battery_level, margin, join_request_time, and inside data — packet_loss_rate, tags and the JS codec result (execResult, execError). The server does not send the status, data.id and data.gateway_available fields from the v0.17 example. data.time comes in ISO 8601 without a time zone, not as 2018-02-17 13:06:22+0000.

Request​

Fields not marked as required may be omitted.

FieldTypeDescription
cmdstringconsume_req
operation_idstringAny string; the server returns it in the response to match the request and the response
downlink_statusbooltrue — also send downlink_status messages. Default false
{
"cmd": "consume_req",
"operation_id": "sub1",
"downlink_status": true
}

Response​

FieldTypeDescription
cmdstringconsume_resp
operation_idstringValue from the request
statusuint81 — the connection is subscribed, 2 — error
consumer_countuint16How many connections of the application are subscribed, including this one. On error 1 — how many are subscribed now; absent on errors 2 and 3
error_code, error_textuint8, stringOnly on error, see below
{
"cmd": "consume_resp",
"operation_id": "sub1",
"status": 1,
"consumer_count": 1
}

Errors​

error_codeerror_textWhat happened
1Consumer limit reachedThe application already has the maximum number of subscribed connections. Find the extra ones with connections_list and close or unsubscribe them
2Already consumedThis connection is already subscribed: by an earlier consume_req or automatically on connect
3Disabled applicationThe application has no non-revoked token left — for example, the tokens were revoked after connecting

The realtime_data message​

FieldTypeDescription
cmdstringrealtime_data
devEuistringDevice DevEUI
devAddrstringDevice DevAddr
dataobjectThe frame and reception parameters, see below
battery_levelfloatBattery level from the device's last answer to the status request (DevStatusAns): 0 — external power, 255 — the device cannot measure the level, otherwise — percent, from 0.4 to 100. null until the server receives such an answer
marginint8SNR margin from the same answer, dB, from −32 to 31. null until the server receives the answer
join_request_timestringTime of the device's last Join Request by the gateway clock, UTC, ISO 8601. null if the server has not seen the device join, e.g. for an ABP device

data fields:

FieldTypeDescription
fcntuint32Uplink frame counter
fportint16Application port. 0 — data holds MAC commands; −1 — the frame has no port and no data
datastringPayload in hex, already decrypted
mtypeuint8Frame type: 2 — Unconfirmed Data Up, 4 — Confirmed Data Up
adrboolThe device has ADR enabled (the ADR bit in the frame header)
ackboolThe device requested an ADR acknowledgement (the ADRACKReq bit). This is not a downlink acknowledgement
foptsstringMAC commands from the FOpts field in hex; an empty string if there are none
datruint8Data rate number (DR) in the device frequency plan
freqfloatReception frequency, MHz
rssiint16RSSI, dBm
lsnrfloatSNR, dB
sizeuint16Size of the whole received LoRaWAN frame (PHYPayload), bytes
timestringReception time by the gateway clock, UTC, ISO 8601 without a time zone, e.g. 2026-10-08T09:47:18.528002
gatewayIdstringEUI of the gateway through which the server received the frame, 16 hex characters
packet_loss_ratefloatFrame loss calculated from gaps in the fcnt counter over the last 20 uplinks, %
tagsobjectApplication and device tags; if keys match, the device tag takes precedence. An empty object if there are no tags
execResultobjectOnly if the application has a JS codec configured. The decodeUplink result: data — the decoded data, errors and warnings — codec messages. null if the codec failed
execErrorstringOnly with a JS codec: the codec error text, or null if there is no error
{
"cmd": "realtime_data",
"devEui": "6F1E570FFE14DBFC",
"devAddr": "78130AE1",
"data": {
"datr": 5,
"rssi": -97,
"lsnr": 8.5,
"data": "0A1B2C3D4E5F6071",
"freq": 868.9,
"time": "2026-10-08T09:47:18.528002",
"ack": false,
"size": 21,
"gatewayId": "0000B827EBFD64DE",
"adr": true,
"fcnt": 1542,
"mtype": 2,
"fopts": "",
"fport": 2,
"packet_loss_rate": 0,
"execResult": {
"errors": [],
"warnings": [],
"data": {
"temperature": 21.5
}
},
"execError": null,
"tags": {
"building": "A"
}
},
"battery_level": 100.0,
"margin": 9,
"join_request_time": "2026-10-01T06:12:40.114233Z"
}

Good to know​

  • One queue per application. If several connections of one application are subscribed, each realtime_data message reaches only one of them: the server hands messages to the connections in turn. For one client to receive all data, keep one subscribed connection per application.
  • Data accumulates while nobody is subscribed. The server keeps uplinks that arrive without subscribers and sends them after subscription — the accumulated ones first, then new ones. By default the queue is deleted together with its data if nobody subscribes to it for 14 days.
  • A message may be lost on a disconnect. The server considers a message delivered as soon as it has sent it to the connection. If the connection drops at that moment, the message is not returned to the queue. Fetch missed data with get_data_req.
  • The subscription lives as long as the connection is open. Subscribe again after reconnecting.
  • Automatic subscription. If automatic subscription is enabled in the application settings, the server subscribes the connection itself right after connected and sends consume_resp without operation_id. In that case the server responds to consume_req with error 2. Automatic subscription does not enable downlink_status: to receive statuses, unsubscribe with unconsume_req and subscribe again with "downlink_status": true.
  • The downlink_status flag is applied only when the subscription is made. If the connection is already subscribed without it, unsubscribe first with unconsume_req.

See also​