Skip to main content

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.

Current ONS version

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 the dataId returned in downlink_data_resp: that one is used for downlink_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 devEui with "allScheduled": true: all scheduled frames of the device are withdrawn. Without the allScheduled flag 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.

FieldTypeDescription
cmdstringcancel_downlink_req
operation_idstringAny string; the server returns it in the response to match the request and the response
dataIduint64dataId or devEui is required. Queue item identifier — to withdraw one frame
devEuistringdataId or devEui is required. Device DevEUI — to withdraw its whole queue; requires allScheduled
allScheduledboolTogether with devEui. true — withdraw all scheduled frames of the device. Default false
{
"cmd": "cancel_downlink_req",
"operation_id": "abc",
"devEui": "6F1E570FFE14DBFC",
"allScheduled": true
}

Response​

FieldTypeDescription
cmdstringcancel_downlink_resp
operation_idstringValue from the request
statusuint81 — the frame is withdrawn, 2 — not withdrawn
cancelStatusstringWithdrawal result, see the table below
reasonstringReason as text
data_iduint64Queue item — for a one-frame withdrawal
dev_euistringThe device
dev_addr, fport, data, mtypestring, uint8, string, uint8Parameters of the withdrawn frame — only for a one-frame withdrawal with cancelStatus = canceled
countuint32Number of withdrawn frames
data_idsarrayWithdrawn queue items — for a whole-queue withdrawal

Fields without a value are omitted from the response.

cancelStatusstatusMeaning
canceled1The frame is withdrawn; for the whole queue — all scheduled frames (count, data_ids)
already_canceled2The frame was already withdrawn; repeating the request is safe
too_late2The 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_found2There is no such queue item, or it belongs to another application
not_downlink2The item with this identifier is not a downlink
error2Neither 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​