Downlink — withdraw data from the queue
Withdraws a downlink frame that is waiting in the queue and has not yet been sent to the device. A class A device receives a downlink only in response to its next uplink, so a frame can wait in the queue for hours and can be withdrawn at any point during that time.
The command is not in the v0.17 description: it was added to the server in August 2026.
Withdrawal works in two modes:
- One frame — by
dataId, the identifier of the queue item on the server. This is not thedataIdreturned indownlink_data_resp: that one is used fordownlink_ack_req. The server returns the queue item identifier only in the response to a whole-queue withdrawal (data_ids): the queuing and history commands do not return it. - The whole device queue — by
devEuiwith"allScheduled": true: all scheduled frames of the device are withdrawn. Without theallScheduledflag the request is rejected, because the queue may hold frames queued by other clients.
Only frames with status 0 (Scheduled) or 4 (Realtime Scheduled) — those not yet handed to a gateway — can be withdrawn. A withdrawn frame is not deleted: in the history (get_downlink_data_req) it stays with status 6 (Canceled) — see frame status. The queue item is looked up within the last month.
Request and response: cancel_downlink_req → cancel_downlink_resp.
Access: a token of any access level; the command withdraws only frames of devices that belong to the application you are connected to.
Request
Fields not marked as required may be omitted.
| Field | Type | Description |
|---|---|---|
cmd | string | cancel_downlink_req |
operation_id | string | Any string; the server returns it in the response to match the request and the response |
dataId | uint64 | dataId or devEui is required. Queue item identifier — to withdraw one frame |
devEui | string | dataId or devEui is required. Device DevEUI — to withdraw its whole queue; requires allScheduled |
allScheduled | bool | Together with devEui. true — withdraw all scheduled frames of the device. Default false |
{
"cmd": "cancel_downlink_req",
"operation_id": "abc",
"devEui": "6F1E570FFE14DBFC",
"allScheduled": true
}
Response
| Field | Type | Description |
|---|---|---|
cmd | string | cancel_downlink_resp |
operation_id | string | Value from the request |
status | uint8 | 1 — the frame is withdrawn, 2 — not withdrawn |
cancelStatus | string | Withdrawal result, see the table below |
reason | string | Reason as text |
data_id | uint64 | Queue item — for a one-frame withdrawal |
dev_eui | string | The device |
dev_addr, fport, data, mtype | string, uint8, string, uint8 | Parameters of the withdrawn frame — only for a one-frame withdrawal with cancelStatus = canceled |
count | uint32 | Number of withdrawn frames |
data_ids | array | Withdrawn queue items — for a whole-queue withdrawal |
Fields without a value are omitted from the response.
cancelStatus | status | Meaning |
|---|---|---|
canceled | 1 | The frame is withdrawn; for the whole queue — all scheduled frames (count, data_ids) |
already_canceled | 2 | The frame was already withdrawn; repeating the request is safe |
too_late | 2 | The frame has already been handed to a gateway or has a final status, or the server picked it up for transmission at the moment of the request |
not_found | 2 | There is no such queue item, or it belongs to another application |
not_downlink | 2 | The item with this identifier is not a downlink |
error | 2 | Neither dataId nor devEui given; whole-queue withdrawal without "allScheduled": true; internal server error |
Response examples
The whole device queue is withdrawn:
{
"cmd": "cancel_downlink_resp",
"operation_id": "abc",
"status": 1,
"cancelStatus": "canceled",
"reason": "Cancelled every scheduled downlink of the device",
"dev_eui": "6F1E570FFE14DBFC",
"count": 2,
"data_ids": [ 48211, 48212 ]
}
The frame has already been handed to a gateway (status 1, Sent):
{
"cmd": "cancel_downlink_resp",
"operation_id": "xyz",
"status": 2,
"cancelStatus": "too_late",
"reason": "Already Sent",
"data_id": 48213,
"dev_eui": "6F1E570FFE14DBFC"
}
See also
- Sending data to a device — the whole scenario and frame statuses.
downlink_purge_req— cancel waiting frames with a high access level token.