Data Storage Device ID Query Not Working

Does anyone have any possible suggestions to address my issue? I am getting uplink when I hit the endpoint that includes all devices but when I hit the endpoint for a specific device, I get a ‘no content’ response.

What relevant output do you see when getting data for all devices, and which curl command are you then using to query for a single one? (You can redact/hide the access key.)

(To format that output, see also How do I format my forum post? [HowTo])

I have a test application in the office that uses Data Storage as it’s primary retrieval means, it calculates the timespan relative to its last retrieve so I know this works. As I use a calculation, I always request a number of seconds, so you may want to try 3600s or 604800s

Usually I find people (clients) get a 204 when the device id isn’t quite right.

In the first instance, can you COPY and paste what you are using, then change the key AND tell us what environment you are using - OS, programming language etc

And whilst we are looking at that, can you confirm you have tried using the Swagger online tool linked from the integration for testing? If you go in to the Data Storage integration there is a link called “go to platform”

This is working for me:

as does this:

curl -X GET --header 'Accept: application/json' --header 'Authorization: key ttn-account-v2.UxRAbhp0NFcfCW3Ye61BDbeyYSXu-RS2F3okEBfiwFw' ''

It’s the multi-level temp sensor outside the office. I’ll revoke the key once you’ve confirmed it gives you some data back.

Hey Nick, thanks responding. I can confirm I have been using the Swagger online tool, which provided me with the curl command for a device with ID dl-pr26_5100

curl -X GET --header 'Accept: application/json' --header 'Authorization: key xxx' ''

This is the command that is currently producing a 204. Even though this curl

curl -X GET --header 'Accept: application/json' --header 'Authorization: key xxx' ''

produces a response similar to this:

    "battery_voltage": "map[value:2.744 displayName:Battery voltage unit:V]",
    "device_id": 5100,
    "device_id_1": "dl-pr26_5100",
    "pressure": "map[displayName:Pressure unit:bar value:0.030670166015625]",
    "protocol_version": 2,
    "raw": "AhPsAAND7VJFCrg=",
    "temperature": "map[displayName:Temperature unit:°C value:14.615625000000009]",
    "time": "2020-10-15T12:49:46.585897243Z"

I have also confirmed that your test example is working for me when I try it. You can revoke your key. Thanks!

Hello Arjan my response to Nick details the curl commands and outputs you asked for. Thanks!

That’s weird. Any chance your payload format decoder is outputting an attribute called device_id? Or, if that is actually outputting device_id_1, then it seems the device id in TTN Console is simply 5100? What if you use 5100 in the URL?

I concur - perhaps it would be useful for you to try:

to get a list of devices as nature & TTN see them.

And/or create a read only key like I did and let one of us try it out for you.

And show us your decoder!

Running produces the following response


Using device id 5100 with endpoint

produces the same 204, no content response

I currently do not have access to the console and decoder, but am working closely with someone who does and will try to get that information ASAP.


If you do a compare and contrast, you’ll notice that the prefix to the url is the application id and the device id is at the end.

So descartes-room-monitor is the application id and descartes-tt-outdoor is the device id

So for this:

I can’t tell if ruchir_dl-pr-26_5100 is some very specific application name or a combination but it definitely fails my sniff test.

And 5100 is clearly wrong, it should be dl-pr26_5100

PS, if you follow the go to platform link from the integration, it would setup most of this in Swagger, all you have to do is hit the authenticate button and add your key.

Hey Nick,

I have been using an authenticated Swagger to produce the responses that I shared. The application ID is indeed ruchir_dl-pr-26_5100.

So that’s one half sorted.

How about testing it with the id that TTN uses:

You could also use the access key you’ve got for the Storage Integration, to subscribe to the uplink data using an MQTT client. That will show you what is in the JSON attribute payload_fields. (And I’m quite sure you’ll see a field device_id that confuses the Data Storage query.)

Like with Mosquitto on a Mac, if you’re in EU868:

mosquitto_sub -v -h -t '#' -u ruchir_dl-pr-26_5100 -P ttn-account-v2.your-access-key

Hey Arjan, I used your example to setup an MQTT client. When I use your command and my access

the program waits without receiving any uplink data even though the sensor sends data every 10 minutes. I confirmed with the Swagger UI that data is still being sent for the sensor. Do I have to update the topic field of the command to something other than -t '#'? I’m currently trying to get access to the console to look at the decoder as well. Thanks!

Using 5100 also produces the same not content response

That # is a wildcard that will show you all messages. So no, no change needed for that. I cannot explain why it doesn’t work; it really should work the correct application id and access key, assuming you’re using EU868. If not, then the server name needs changing too.

Where can I find the server name in the event that I am not using EU868?

In the documentation that I already linked to above. (And sorry, I am out of here, this is too annoying for me. Success.)

1 Like


Both device ID queries of dl-pr26_5100 and 5100 produce not response.

I was able to get access to the decoder.

var decentlab_decoder = {
  /* device-specific parameters */
    Pmin: 0.0,
    Pmax: 1.0
    {length: 2,
     values: [{name: 'pressure',
               displayName: 'Pressure',
               convert: function (x) { return (x[0] - 16384) / 32768 * (this.PARAMETERS.Pmax - this.PARAMETERS.Pmin) + this.PARAMETERS.Pmin; },
               unit: 'bar'},
              {name: 'temperature',
               displayName: 'Temperature',
               convert: function (x) { return (x[1] - 384) * 0.003125 - 50; },
               unit: '°C'}]},
    {length: 1,
     values: [{name: 'battery_voltage',
               displayName: 'Battery voltage',
               convert: function (x) { return x[0] / 1000; },
               unit: 'V'}]}
  read_int: function (bytes, pos) {
    return (bytes[pos] << 8) + bytes[pos + 1];
  decode: function (msg) {
    var bytes = msg;
    var i, j;
    if (typeof msg === 'string') {
      bytes = [];
      for (i = 0; i < msg.length; i += 2) {
        bytes.push(parseInt(msg.substring(i, i + 2), 16));
    var version = bytes[0];
    if (version != this.PROTOCOL_VERSION) {
      return {error: "protocol version " + version + " doesn't match v2"};
    var deviceId = this.read_int(bytes, 1);
    var flags = this.read_int(bytes, 3);
    var result = {'protocol_version': version, 'device_id': deviceId};
    // decode payload
    var pos = 5;
    for (i = 0; i < this.SENSORS.length; i++, flags >>= 1) {
      if ((flags & 1) !== 1)
      var sensor = this.SENSORS[i];
      var x = [];
      // convert data to 16-bit integer array
      for (j = 0; j < sensor.length; j++) {
        x.push(this.read_int(bytes, pos));
        pos += 2;
      // decode sensor values
      for (j = 0; j < sensor.values.length; j++) {
        var value = sensor.values[j];
        if ('convert' in value) {
          result[] = {displayName: value.displayName,
                                value: value.convert.bind(this)(x),
                                unit: value.unit};
    return result;
function Decoder(bytes, port) {
  return decentlab_decoder.decode(bytes);


I suspect I know what the answer is, but given you lack of success so far, I think this is the best course of action.

Can you get the decoder removed for a while so the Data Storage just gets the raw data, un-affected by the JS decoder.