Sending data to a device
A downlink is data from the server to a device: a command, a new setting, or a reply to a request. Sending is asynchronous: the server queues the frame, immediately responds with a dataId identifier, and transmits the frame when the device has a receive window open. The server then sends separate messages to report what happens to the frame.
When a device can receive a frame
| Class | When it receives | When the frame goes out |
|---|---|---|
| A | Only in two short windows (RX1, RX2) right after its own uplink | After the device's next uplink — minutes or hours later |
| C | The receiver is always on | Right after queuing |
| B | — | The server does not support class B yet |
For more about classes, see Device classes. The class of a particular device is returned by dev_lw_class_req.
Command order
- Subscribe to data and frame statuses:
consume_reqwith"downlink_status": true. The flag is applied only when the subscription is made: if the connection is already subscribed without it, unsubscribe first withunconsume_req. - Check that the data fits:
max_dl_data_req. - Queue the frame:
downlink_data_req. Keep thedataIdfrom the response: it identifies the frame when you check its status. - Wait for a
downlink_statusmessage with a final status. If no message arrives, request the status withdownlink_ack_req. - If the frames have not left yet and are no longer needed, withdraw all scheduled frames of the device:
cancel_downlink_reqwithdevEuiand"allScheduled": true. A single frame cannot be withdrawn by thedataIdfrom step 3.
A class A device — the frame waits in the queue until the next uplink:
A class C device — the server transmits the frame right away, without waiting for an uplink:
A frame for a class C device goes through the gateway that received the device's last uplink best. Until the device has sent at least one uplink after joining the network, the server does not know which gateway to use, and the frame stays in the queue.
Frame status
The frame status is visible in three places:
- in the
downlink_statusmessage the server sends on its own if the subscription was made with"downlink_status": true; - in the
downlink_ack_reqresponse — on request; - in the
get_downlink_data_reqhistory — for a period.
| Code | Name | Meaning | Final |
|---|---|---|---|
| 0 | Scheduled | The frame is in the queue, waiting for a receive window | no |
| 4 | Realtime Scheduled | A realTime frame is waiting for the nearest window | no |
| 1 | Sent | The frame has been handed to a gateway; the server is waiting for the transmission acknowledgement | no |
| 14 | DC Limit | The gateway airtime budget is exhausted; the frame stays in the queue and goes out later | no |
| 3 | Delivered | The gateway radiated the frame. This is an acknowledgement from the gateway, not from the device | yes |
| 2 | Late | The gateway rejected the frame: too late for the receive window | yes |
| 9 | Too Early | The gateway rejected the frame: too early to transmit | yes |
| 10 | Collision | The gateway rejected the frame: another transmission is already scheduled for that time | yes |
| 11 | TX Freq Rejected | The gateway does not support the transmission frequency | yes |
| 12 | TX Power Rejected | The gateway does not support the transmit power | yes |
| 13 | GPS Unlocked | Without GPS sync the gateway cannot transmit at the scheduled time | yes |
| 7 | TX_ACK Timeout | The gateway did not acknowledge the transmission within 10 seconds | yes |
| 5 | Realtime Late | A realTime frame did not make it into a window within 2 seconds and was dropped | yes |
| 8 | Expired | The ttl ran out (1 hour by default) — the frame was dropped | yes |
| 6 | Canceled | The frame was withdrawn with cancel_downlink_req or downlink_purge_req | yes |
The downlink_status message
The server sends it on every status change except queuing (0 and 4) and withdrawal (6).
- Statuses go to the application that owns the device — for frames sent by any means, not only through the WebSocket API.
- There is one status queue per application. If several connections of one application are subscribed, each message reaches only one of them — the same as
realtime_datamessages. - The server keeps undelivered messages for 5 minutes. If the connection was down for longer, request the status with
downlink_ack_req. - In the current server version the status subscription is not removed on unsubscribing or closing the connection, so after a reconnect some
downlink_statusmessages may not arrive. Check the final status of important frames withdownlink_ack_req.
| Field | Type | Description |
|---|---|---|
cmd | string | downlink_status |
devEui, devAddr | string | The device |
dataId | uint32 | Frame identifier from downlink_data_resp |
downlink_status | uint8 | Status code, see the table above |
downlink_status_text | string | Status name |
downlink_status_time | string | When the status was set, UTC, ISO 8601 |
emit_ts | string | When the server sent the message, UTC, ISO 8601. Helps to order messages that arrived out of order |
{
"cmd": "downlink_status",
"devEui": "6F1E570FFE14DBFC",
"devAddr": "78130AE1",
"dataId": 3046127811,
"downlink_status": 3,
"downlink_status_text": "Delivered",
"downlink_status_time": "2026-10-08T09:47:21.402113+00:00",
"emit_ts": "2026-10-08T09:47:21.415870+00:00"
}
If a frame was not delivered
| Status | What to do |
|---|---|
| 8 Expired | The device did not report while the frame was waiting. Increase ttl to the device's uplink interval, with a margin |
| 5 Realtime Late | No receive window opened within 2 seconds. Do not set realTime for deferred sending |
| 2 Late, 9 Too Early, 10 Collision | The gateway could not transmit at the scheduled time. Send the frame again |
| 11 TX Freq Rejected | The transmission frequency does not suit the gateway. Remove freq from the request or check the device frequency plan |
| 12 TX Power Rejected | The transmit power does not suit the gateway. Check the device frequency plan and the gateway settings |
| 13 GPS Unlocked | Check the GPS antenna and the gateway synchronization |
| 7 TX_ACK Timeout | Check the gateway connection to the server |
| 14 DC Limit | Nothing to do: the frame stays in the queue and goes out later |
The device does not acknowledge reception: the server sends frames as Unconfirmed Data Down. The only way to make sure the device executed a command is its reply in an uplink.
Commands of the group
| Command | Purpose |
|---|---|
dev_lw_class_req | Get the device class — it determines when the frame goes out |
max_dl_data_req | Get the number of bytes that fit into a frame |
downlink_data_req | Queue a frame |
downlink_ack_req | Get the frame status on request |
cancel_downlink_req | Withdraw the scheduled frames of a device that have not left yet |
downlink_purge_req | Clear the device queue: cancel frames with status 0 (high access level token) |