thethings.iO Developer Center

Here you'll find everything you need to get started or go deep on developing IoT Products, Applications and Services with the thethings.iO IoT Platform.

Suggest Edits

HTTP Status Codes

Our API uses the following status codes:

 

The thethings.iO API attempts to return appropriate HTTP status codes for every request.

HTTP Status Code
Message
Description

200

OK

Success!

201

Created

Created / Pushed!

304

Not Modified

There was no new data to return

400

Bad Request

The request was invalid or cannot be otherwise served. An accompanying error message will explain further.

401

Unauthorized

Authentication credentials were missing or incorrect.

403

Forbidden

The request is understood, but it has been refused or access is not allowed. An accompanying error message will explain why. This code is used when requests are being denied due to rate limits.

404

Not found

The URI requested is invalid or the resource requested, such as a user, does not exists. Also returned when the requested format is not supported by the requested method.

410

Gone

This resource is gone. Used to indicate that an API endpoint has been turned off. For example: “thethings.iO REST API v1 will soon stop functioning. Please migrate to API v2.”

429

Too Many Requests

Returned in API v2 when a request cannot be served due to the application’s rate limit having been exhausted for the resource.

500

Internal Server Error

Something is broken. Please contact with support.

502

Bad Gateway

thethings.iO is down or being upgraded.

503

Service Unavailable

thethings.iO servers are up, but overloaded with requests. Try again later.

504

Gateway timeout

thethings.iO servers are up, but the request couldn’t be serviced due to some failure within our stack. Try again later.

Suggest Edits

Thing Activate

Activates a thing with an activation code. The result is a thing token. You will be able to retrieve this thing token at any time from the panel.

 
posthttps://api.thethings.io/v2/things
curl --request POST \
  --url https://api.thethings.io/v2/things
var request = require("request");

var options = { method: 'POST', url: 'https://api.thethings.io/v2/things' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/things");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "status": "created",
  "message": "thing activated",
  "thingToken": "jfFWohgaKzJ5UEwqrry5kg5g9hyGWt0T2QP9wLVzw",
  "thingId": "uufkAJsdqkZQ-gX7nJzm9cBoEDeDk24NylhazQAwN8"
}
  {
    "status": "error",
    "message": "activation code not found"
  }

Body Params

activationCode
string
productId
string
 
Suggest Edits

Thing Write

Writes the records of data from the thing to the specified THING_TOKEN. Only alphanumeric characters and ".", "-", "" symbols are admited for the resource name "key".

 
posthttps://api.thethings.io/v2/things/THING_TOKEN
curl --request POST \
  --url https://api.thethings.io/v2/things/THING_TOKEN
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/things/THING_TOKEN");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{"status":"success","message":"created"}
{"status": "error", "message": "Thing token doesn't exist"}

Path Params

THING_TOKEN
string
required

Query Params

store
boolean

Default value: TRUE. If FALSE, values won't be stored in the cloud.

broadcast
boolean

Default value: TRUE. If FALSE, values won't be broadcasted between other channels in real-time

Body Params

values
array of objects
required
key
value
 

Remember to replace THING_TOKEN with the thing token that you got when you activated your thing.

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{ "values": [ { "key": "fun", "value": "5000" } ] }'
  \
  -X POST "https://api.thethings.io/v2/things/THING_TOKEN" -k

Geolocation

If your thing can change its location you can geolocate your values adding the geo parameter in the body:

{
  "values":
  [{
    "key": "my-geolocated-key",
    "value" : 23,
    "geo" : {
      "lat" : 41.4121132,
      "long" : 2.2199454
    }
  }]
}

Custom Timestamp

When thethings.iO receives a value, it also stores the current date and time in UTC format. But sometimes your thing can't or you do not want it to send the values at the time the sensor reading was done (i.e. your thing doesn't have connectivity or you want to save battery). To solve this use case, you can send a batch of values and indicate the time on each. The values don't need to be sorted by time, they will be sorted by our storage system automatically. The format is YYYYMMDDHHmmss. Notice thethings.iO considers all times to be in UTC.

{
  "values":
  [{
    "key": "my-batch-key",
    "value" : 23,
    "datetime" : "20150520130000"
  },
  {
    "key": "my-batch-key",
    "value" : 24,
    "datetime" : "20150520140000"
  },
  {
    "key": "my-batch-key",
    "value" : 25,
    "datetime" : "20150520150000"
  },
  {
    "key": "my-batch-key",
    "value" : 22,
    "datetime" : "20150520120000"
  }]
}

You can get the server time by calling:

GET https://api.thethings.io/v2/utils/date?thingToken=THING_TOKEN&format=FORMAT

Where FORMAT can be UTC (default) or unix_timestamp

Suggest Edits

Thing Read

This method returns the values of the resource with the specified RESOURCE_KEY from the corresponding THING_TOKEN. To read data, use the operation GET /things/ with the thing token and the key that you are using to store the values.

 
gethttps://api.thethings.io/v2/things/THING_TOKEN/resources/RESOURCE_KEY
curl --request GET \
  --url https://api.thethings.io/v2/things/THING_TOKEN/resources/RESOURCE_KEY
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/resources/RESOURCE_KEY' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/resources/RESOURCE_KEY")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN/resources/RESOURCE_KEY");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/resources/RESOURCE_KEY"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

[
  {
    "value": "9000", 
    "datetime": "2015-01-30T15:35:33.000Z" 
  }
] 
{"status": "error", "message": "Thing token doesn't exist"}
# If you try to read a resource with a key to which you never have written before, you will get the this error. Remember to change RESOURCE_KEY for a valid key:
{"status": "error","message": "resource not found"}

Path Params

THING_TOKEN
string
required
RESOURCE_KEY
string
required

Query Params

limit
int32

Max. number of values to be returned (Max.: 100)

startDate
string

The minimum date (Format: YYYYMMDDHHmmss). The default date is Jan 1st 1970.

endDate
string

The minimum date (Format: YYYYMMDDHHmmss). The default date is the end of times (javascript).

 

Remember to replace KEY by the key that you used on the WRITE operation ('fun' was the key used in the example code).

Suggest Edits

Thing Subscribe

With this method you can subscribe to the thing channel and get real-time updates from all the thing's keys (resources). The subscription endpoint creates a streaming channel and we keep the channel open depending on the keep alive that you send. If no keep alive is set, your router or our server will close the channel at its sole discretion.

You will need a compatible client. To subscribe from a browser we recommend to use Websocket. REST API subscription is not reliable on browsers.

To test the real-time updates from the command line, you will need to open two consoles. One for the subscription curl command, and another to do the curl write commands.

 
gethttps://api.thethings.io/v2/things/THING_TOKEN
curl --request GET \
  --url https://api.thethings.io/v2/things/THING_TOKEN
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{"status":"success", "message":"subscribed"}
{"status":"error", "message":"Thing with thing token 'Eyixxxxxxx-xxxxxxxx' not found."}

Path Params

THING_TOKEN
string
required

Query Params

keepAlive
int32

Keep alive for keeping the channel open.

 

Remember to replace THING_TOKEN with the thing token that you got when you activated your thing.

Suggest Edits

Thing Magic Resources Write

Magic resources are specials resources that start with $, and have some special behaviors, like trigger some common task, or update static data. These resources can be used as the others using read and write operations.

 
posthttps://api.thethings.io/v2/things/THING_TOKEN
curl --request POST \
  --url https://api.thethings.io/v2/things/THING_TOKEN
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/things/THING_TOKEN");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

THING_TOKEN
string
required

Body Params

values
array of objects
required

Example: key: $geo and value : {"type": "Point","coordinates": [2.154007, 41.390205]}

key
value
 

Remember to replace THING_TOKEN with the thing token that you got when you activated your thing.

Magic resource handlers are processed asynchronously: mixing various magic resources in a single request may have an unexpected behavior because order might not be respected.

$geo resource

This resource allows the update of the current thing position in GeoJSON format.

GeoJSON and legacy [long, lat] pairs are accepted as valid input value, or you can use the geo attribute: the final value will be saved in GeoJSON format.

curl -H "Content-Type: application/json" \
       -d "... see below ..." \
       -X POST "http://api.thethings.io/v2/things/THING_TOKEN"

  {
    "values":
      [{
          "key": "$geo",
          "value" : {
                  "type": "Point",
                  "coordinates": [2.154007, 41.390205]
          }
        },
        // OR using legacy [long, lat]
        {
          "key": "$geo",
          "value" : [2.154007, 41.390205]
        },
        // OR using geo attribute object
        {
          "key": "$geo",
          "value" : null,
          "geo" : {
                  "lat": 41.390205,
                  "long": 2.154007
          }
        }]
  }

$settings resource

This resource allows the update of thing settings meta-data store. It also permits to set a single value at path (in dot separated format).

  curl -H "Content-Type: application/json" \
       -d "... see below ..." \
       -X POST "http://api.thethings.io/v2/things/THING_TOKEN"

  {
    "values":
      [{
          "key": "$settings",
          "value" : {
                  "name": "My Thing",
                  "foo": "bar"
          }
        },
        // OR using path
        {
          "key": "$settings.name",
          "value" : "My Thing"
        }]
  }
Suggest Edits

Thing Magic Resources Read

Magic resources are specials resources that start with $, and have some special behaviors, like trigger some common task, or update static data. These resources can be used as the others using read and write operations.

 
gethttps://api.thethings.io/v2/things/THING_TOKEN/resources/$MAGIC_RESOURCE
curl --request GET \
  --url 'https://api.thethings.io/v2/things/THING_TOKEN/resources/$MAGIC_RESOURCE'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/resources/$MAGIC_RESOURCE' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/resources/$MAGIC_RESOURCE")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN/resources/$MAGIC_RESOURCE");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/resources/$MAGIC_RESOURCE"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

THING_TOKEN
string
required
$MAGIC_RESOURCE
string
required
 

Remember to replace THING_TOKEN with the thing token that you got when you activated your thing and $MAGIC_RESOURCE with the magic resource name (see below).

Magic resource handlers are processed asynchronously: mixing various magic resources in a single request may have an unexpected behavior because order might not be respected.

$geo resource

This resource allows the retrieval of the current thing position in GeoJSON format.

curl -i -H "Accept: application/json" \
  -X GET "https://api.thethings.io/v2/things/THING_TOKEN/resources/$geo" \
  -k
[
  {
    "key": "$geo",
    "value": {
      "type": "Point",
      "coordinates": [2.154007, 41.390205]
    }
  }
]

$settings resource

This resource allows the retrieval of the thing settings meta-data storage. It also permits to get a single value at path (in dot separated format).

curl -i -H "Accept: application/json" \
  -X GET "https://api.thethings.io/v2/things/THING_TOKEN/resources/$settings.name" \
  -k
[
  {
    "key": "$settings.name",
    "value": "My Thing"
  }
]
Suggest Edits

Get Resources

Returns the names of the resources of the thing.

 
gethttps://api.thethings.io/v2/things/THING_TOKEN/resources
curl --request GET \
  --url https://api.thethings.io/v2/things/THING_TOKEN/resources
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/resources' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/resources")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN/resources");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/resources"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

  {
    "status": "success",
    "resources": [
      "LED",
      "TAXI",
      "Yun",
      "demo_resource",
      "number",
      "random",
      "test"
    ]
  }

Path Params

THING_TOKEN
string
required
 

.

Suggest Edits

Add Tag

Add tag to a thing.

 
posthttps://api.thethings.io/v2/things/THING_TOKEN/tags
curl --request POST \
  --url https://api.thethings.io/v2/things/THING_TOKEN/tags
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/tags' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/tags")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/things/THING_TOKEN/tags");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/tags"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "status": "success",
    "tags": [
        {
            "_id": "barcelona",
            "name": "Barcelona"
        }
    ]
}

Path Params

THING_TOKEN
string
required

Body Params

name
string

Headers

Content-Type
string
 
Suggest Edits

Get Tags

Returns the tags of the thing.

 
gethttps://api.thethings.io/v2/things/THING_TOKEN/tags
curl --request GET \
  --url https://api.thethings.io/v2/things/THING_TOKEN/tags
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/tags' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/tags")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN/tags");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/tags"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "status": "success",
  "tags": [
    {
      "_id": "barcelona",
      "name": "Barcelona"
    }
  ]
}
# No tags defined yet
{
  "status": "success",
  "tags": []
}

Path Params

THING_TOKEN
string
required

Headers

Content-Type
string
 
Suggest Edits

Delete Tags

 
deletehttps://api.thethings.io/v2/things/THING_TOKEN/tags/TAG_ID
curl --request DELETE \
  --url https://api.thethings.io/v2/things/THING_TOKEN/tags/TAG_ID
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/tags/TAG_ID' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/tags/TAG_ID")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://api.thethings.io/v2/things/THING_TOKEN/tags/TAG_ID");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/tags/TAG_ID"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

# tags show the list of tags that remain after deletion
{
    "status": "success",
    "tags": [
        {
            "_id": "barcelona",
            "name": "Barcelona"
        }
    ]
}

Path Params

THING_TOKEN
string
required
TAG_ID
string
required

Headers

Content-Type
string
 
Suggest Edits

Register

Register an app user at thethings.iO Platform. This endpoint also logs the user in (returns the session token and roles), so you don't have to do another API call to log him in.

 
posthttps://api.thethings.io/v2/register
curl --request POST \
  --url https://api.thethings.io/v2/register
var request = require("request");

var options = { method: 'POST', url: 'https://api.thethings.io/v2/register' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/register")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/register");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/register"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "token": "THING_TOKEN",
  "expirationDate": 31536000, //seconds till token expiration
  "roles": {
    "RSRC_description": {
      "OTLoG_xxxxxxxx": {
        "get": true,
        "post": true,
        "grant": true,
        "put": true,
        "delete": true
      }
    },
    "RSRC_temperature": {
      "OTLoG_xxxxxxxx": {
        "get": true,
        "post": true,
        "grant": true,
        "put": true,
        "delete": true
      }
    }
  },
  "status": "success",
  "message": "user created"
}

Body Params

email
string

The user's email address

password
string

A hard to guess password

app
string

The appID given in the panel

 
Suggest Edits

Login

Login an app user at thethings.iO Platform. Returns the session token and roles. The object "roles" identifies the resources and things that the user has authorized the app to access.

 
posthttps://api.thethings.io/v2/login
curl --request POST \
  --url https://api.thethings.io/v2/login
var request = require("request");

var options = { method: 'POST', url: 'https://api.thethings.io/v2/login' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/login")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/login");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/login"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "token": "THING_TOKEN",
  "expirationDate": 31536000, //seconds till token expiration
  "roles": {
    "RSRC_description": {
      "OTLoG_xxxxxxxx": {
        "get": true,
        "post": true,
        "grant": true,
        "put": true,
        "delete": true
      }
    },
    "RSRC_temperature": {
      "OTLoG_xxxxxxxx": {
        "get": true,
        "post": true,
        "grant": true,
        "put": true,
        "delete": true
      }
    }
  }
}

Body Params

email
string

The user's email address

password
string

A hard to guess password

app
string

The appID given in the panel

 
Suggest Edits

Accessing the user's resources

To be able to access the user’s resources (i.e. the things data) the user must have authorized the app to see these resources.

To check which resources has the user available we can call the GET /resources endpoint. Then, if we are interested in some of his resources we can ask the user to grant the app permissions to use them. For each resource and thing, there are three types of permissions: get, post and grant. Get and post are equivalent to read and write. Grant allows the app to grant this permission to more users.

When an app requests permissions, the platform sends a confirmation email in background to the user to check if the user is aware of this action. The user must confirm before the app can access the data. There is an exception, when the app is an official app the permissions are granted automatically.

 

.

Suggest Edits

Get resources

Get the user's resources and the things associated to each resource.

 
gethttps://api.thethings.io/v2/me/resources
curl --request GET \
  --url https://api.thethings.io/v2/me/resources \
  --header 'authorization: Authorization'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/me/resources',
  headers: { authorization: 'Authorization' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/resources")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Authorization'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/me/resources");
xhr.setRequestHeader("authorization", "Authorization");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/resources"

headers = {'authorization': 'Authorization'}

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

# This result tells us that the user has the resource "temperature" for the thing with ID "thingId1" and the thing with ID "thingId2"
[
  {
    "name" : "temperature",
    "things" : [
      "thingId1",
      "thingId2"
    ]
  },
  {
    "name": "another resource name",
    "things" : [
      "thingId2",
      "thingId3",
      ...
    ]
  },
    ...
]

Headers

Authorization
string
required

SESSION_TOKEN

 
Suggest Edits

Grant

Asks the user to grant permissions to the app, so the app can access the user's resources.

 
puthttps://api.thethings.io/v2/me/grant
curl --request PUT \
  --url https://api.thethings.io/v2/me/grant
var request = require("request");

var options = { method: 'PUT', url: 'https://api.thethings.io/v2/me/grant' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/grant")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://api.thethings.io/v2/me/grant");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/grant"

response = requests.request("PUT", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  status: 'success',
  message: 'granted'
}
 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -d '{"permissions": {"temperature":{"thingId1":{"get": true, "grant": true}}}}' \
  -X PUT "https://api.thethings.io/v2/me/grant" -k
Suggest Edits

Sharing resources

When a user wants to give access to his or her resources to another user, the app can grant the endpoint. But this time the app has to pass the email of the granted user. The granted user will also receive an email to confirm this action.

 
puthttps://api.thethings.io/v2/me/grant
curl --request PUT \
  --url https://api.thethings.io/v2/me/grant
var request = require("request");

var options = { method: 'PUT', url: 'https://api.thethings.io/v2/me/grant' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/grant")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://api.thethings.io/v2/me/grant");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/grant"

response = requests.request("PUT", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  status: 'success',
  message: 'granted'
}

Body Params

email
string
permissions
object
 
 
# In the next example, we let the user’s friend read the temperature of the thing with ID "thingId1". She won’t be able to grant this resource to anybody else, as we aren’t granting her the grant permission. Also it is not possible to grant permissions that the session token doesn’t have.
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -d '{"email": "friend@email.com", permissions": {"temperature":{"thingId1":{"get": true}}}}' \
  -X PUT "https://api.thethings.io/v2/me/grant" -k
Suggest Edits

Get resource values

This endpoint returns the values of the specified resource.

 
gethttps://api.thethings.io/v2/me/resources/RESOURCE
curl --request GET \
  --url https://api.thethings.io/v2/me/resources/RESOURCE
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/me/resources/RESOURCE' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/resources/RESOURCE")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/me/resources/RESOURCE");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/resources/RESOURCE"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Query Params

limit
int32

Max. number of values to be returned (Max.: 100)

startDate
string

The min date (format: YYYYMMDDHHmmss). The default is Jan 1st 1970.

endDate
string

The max date (format: YYYYMMDDHHmmss). The default is the end of times (javascript).

 
curl -i -H "Accept: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -X GET "https://api.thethings.io/v2/me/resources/temperature" -k
{
  "thingId1" : [
    {"value":15, "datetime" : "20150202T220035.00Z"},
    {"value":17, "datetime" : "20150202T210035.00Z"}
  ]
} 
Suggest Edits

Subscribe to resource values

Endpoint to subscribe to the real-time updates. Once subscribed, you will receive a message each time that the resource receives a new value.

If there are no updates the server will send {} after the interval you specified for keepAlive. You should also keep a timer, and if you don’t receive updates after the keepAlive time is expired, yo have to resubscribe. This could happen if the Wi-Fi is down or something happens to the connection.

To subscribe from a browser we recommend to use Websocket. REST API subscription is not reliable on browsers.

 
gethttps://api.thethings.io/v2/me/resources/RESOURCE?subscribe=true&keepAlive=TIME_MS
curl --request GET \
  --url 'https://api.thethings.io/v2/me/resources/RESOURCE?keepAlive=TIME_MS&subscribe=true'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/me/resources/RESOURCE',
  qs: { keepAlive: 'TIME_MS', subscribe: 'true' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/resources/RESOURCE?keepAlive=TIME_MS&subscribe=true")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/me/resources/RESOURCE?keepAlive=TIME_MS&subscribe=true");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/resources/RESOURCE"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

[
  {
    "value":15,
    "id": "thingId1"
  }
]

Path Params

{RESOURCE}
string
required
{TIME_MS}
int32
required

Headers

Authorization
string

SESSION_TOKEN

 
Suggest Edits

Get thing's description

There is a special resource called description that can contains meta data about the thing. This meta data could be the name of the thing (chosen by the user), geocoordinates, JSON objects and any other data the developer wants to put there.

This resource is accessible the same way as all the resources with get and put requests.

Before you modify this resources, you have to get the actual description value, change the properties you want to modify and then store the complete document again.

 
gethttps://api.thethings.io/v2/me/resources/description
curl --request GET \
  --url https://api.thethings.io/v2/me/resources/description
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/me/resources/description' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/resources/description")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/me/resources/description");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/resources/description"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results
 

.

Suggest Edits

Update thing's description

There is a special resource called "description" that can contain meta data about the thing. This meta data could be the name of the thing (chosen by the user), geocoordinates, JSON objects and any other data the developer wants to put there.

This resource is accesible the same way as all the resources with get and put requests.

Before you modify this resources, you have to get the actual description value, change the properties you want to modify and then store the complete document again.

 
puthttps://api.thethings.io/v2/me/resources/description/THING_ID
curl --request PUT \
  --url https://api.thethings.io/v2/me/resources/description/THING_ID
var request = require("request");

var options = { method: 'PUT',
  url: 'https://api.thethings.io/v2/me/resources/description/THING_ID' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/resources/description/THING_ID")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://api.thethings.io/v2/me/resources/description/THING_ID");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/resources/description/THING_ID"

response = requests.request("PUT", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

THING_ID
string
required
 
Suggest Edits

Get User Settings

Sometimes the app needs to store additional data about the user like gender, avatar, hair color, etc. In that case the app can use the endpoint '/me/settings' in order to set and get the user’s settings. The user’s settings are not meant to store large amounts of data. It’s more likely a small key/value store.

Retrieve the settings object.

 
gethttps://api.thethings.io/v2/me/settings
curl --request GET \
  --url https://api.thethings.io/v2/me/settings \
  --header 'authorization: Authorization'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/me/settings',
  headers: { authorization: 'Authorization' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/settings")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Authorization'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/me/settings");
xhr.setRequestHeader("authorization", "Authorization");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/settings"

headers = {'authorization': 'Authorization'}

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "hair-color" : "pink",
  "phones" : ["123456", "998965"]
}

Headers

Authorization
string
required

SESSION_TOKEN

 
Suggest Edits

Update User Settings

Sometimes the app needs to store additional data about the user like gender, avatar, hair color, etc. In that case the app can use the endpoint '/me/settings' in order to set and get the user’s settings. The user’s settings are not meant to store large amounts of data. It’s more likely a small key/value store.

Updates the settings key/value object.

There is a special key password that will update the user’s password with the app.

 
puthttps://api.thethings.io/v2/me/settings
curl --request PUT \
  --url https://api.thethings.io/v2/me/settings \
  --header 'authorization: Authorization'
var request = require("request");

var options = { method: 'PUT',
  url: 'https://api.thethings.io/v2/me/settings',
  headers: { authorization: 'Authorization' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/me/settings")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)
request["authorization"] = 'Authorization'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://api.thethings.io/v2/me/settings");
xhr.setRequestHeader("authorization", "Authorization");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/me/settings"

headers = {'authorization': 'Authorization'}

response = requests.request("PUT", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  status: 'success',
  message: 'updated'
}

Headers

Authorization
string
required

SESSION_TOKEN

 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -d '{"hair-color": "pink", "phones": ["13246578","99833212"]}' \
  -X PUT "https://api.thethings.io/v2/me/settings" -k

If your app needs to store more complex data please look at the section "Objects. Storing App data".

Suggest Edits

Get Server Date

Retrieve the date of the server. The parameter format accepts two values: 'UTC' and 'unix_timestamp'.

 
gethttps://api.thethings.io/v2/utils/date/?format=FORMAT
curl --request GET \
  --url 'https://api.thethings.io/v2/utils/date/?format=FORMAT'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/utils/date/',
  qs: { format: 'FORMAT' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/utils/date/?format=FORMAT")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/utils/date/?format=FORMAT");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/utils/date/"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "date": "2016-03-15T14:14:09.051Z",
  "values": [
    {
      "value": "2016-03-15T14:14:09.051Z"
    }
  ]
}

Path Params

FORMAT
string
required

Accepts two values: 'UTC' and 'unix_timestamp'.

Headers

Authorizarion
string

SESSION_TOKEN

 
curl -i -H "Accept: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -X GET "https://api.thethings.io/v2/utils/date/?format=UTC" -k
 
Suggest Edits

Store an object

This endpoint lets you store an object as a JSON string. If you don’t specify an "_id", the system will automatically assign a random ID. Returns error if the "_id" already exists for that collection.

 
posthttps://api.thethings.io/v2/classes/me/ID_COLLECTION
curl --request POST \
  --url https://api.thethings.io/v2/classes/me/ID_COLLECTION
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.thethings.io/v2/classes/me/ID_COLLECTION' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/classes/me/ID_COLLECTION")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.thethings.io/v2/classes/me/ID_COLLECTION");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/classes/me/ID_COLLECTION"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "status": "success",
  "message":"created",
  "id":"25"
} 

Path Params

{ID_COLLECTION}
string
required
 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -d '{"_id": "25", "name": "Dubstep"}' \
  -X POST "https://api.thethings.io/v2/classes/me/Playlists" -k

You can set the "_id" at the path, too:

POST https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY
Suggest Edits

Delete an object

Delete an object by "_id".

 
deletehttps://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY
curl --request DELETE \
  --url https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY \
  --header 'authorization: Authorization'
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY',
  headers: { authorization: 'Authorization' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)
request["authorization"] = 'Authorization'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY");
xhr.setRequestHeader("authorization", "Authorization");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY"

headers = {'authorization': 'Authorization'}

response = requests.request("DELETE", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "status": "success",
  "message": "deleted"
}

Path Params

ID_COLLECTION
string
required
PRIMARY_KEY
int32
required

Headers

Authorization
string
required

SESSION_TOKEN

 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -X DELETE "https://api.thethings.io/v2/classes/me/Playlists/25" -k
Suggest Edits

Update an object

Change the values of an object. If there are some values which are not overwritten, these values will not be deleted.

 
puthttps://api.thethings.io/v2/things/ID_COLLECTION/PRIMARY_KEY
curl --request PUT \
  --url https://api.thethings.io/v2/things/ID_COLLECTION/PRIMARY_KEY
var request = require("request");

var options = { method: 'PUT',
  url: 'https://api.thethings.io/v2/things/ID_COLLECTION/PRIMARY_KEY' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/ID_COLLECTION/PRIMARY_KEY")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("PUT", "https://api.thethings.io/v2/things/ID_COLLECTION/PRIMARY_KEY");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/ID_COLLECTION/PRIMARY_KEY"

response = requests.request("PUT", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  status: 'success',
  message: 'updated'
}            

Path Params

ID_COLLECTION
string
required
PRIMARY_KEY
int32
required

Headers

Authorization
string

SESSION_TOKEN

 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_ TOKEN" \
  -d '{"name": "Dubstep Mix", "duration": 180}' \
  -X PUT "https://api.thethings.io/v2/classes/me/Playlists/25" -k
            
Suggest Edits

Get Object

Returns the object stored with the specified key.

 
gethttps://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY
curl --request GET \
  --url https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/classes/me/ID_COLLECTION/PRIMARY_KEY"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

ID_COLLECTION
string
required
PRIMARY_KEY
int32
required

Headers

Authorization
string

SESSION_TOKEN

 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -X GET "https://api.thethings.io/v2/classes/me/Playlists/25" -k
{
  "results" : [
    {
      _id: 25,
      "name": "Dubstep Mix",
      "duration" : 180
    }
  ]
}
Suggest Edits

Get collection of objects

Returns all the collection's objects sorted by primary key in descending order.

 
gethttps://api.thethings.io/v2/classes/me/ID_COLLECTION
curl --request GET \
  --url https://api.thethings.io/v2/classes/me/ID_COLLECTION
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/classes/me/ID_COLLECTION' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/classes/me/ID_COLLECTION")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/classes/me/ID_COLLECTION");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/classes/me/ID_COLLECTION"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

ID_COLLECTION
string
required

Headers

Authorization
string

SESSION_TOKEN

 
curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SESSION_TOKEN" \
  -X GET "https://api.thethings.io/v2/classes/me/Playlists" -k
{
  "results" : [
    {
      _id: 25,
      "name": "Dubstep Mix",
      "duration" : 180
    },
    {
      _id: 20,
      "name": "Classic",
      "duration" : 90
    }
  ]
}
Suggest Edits

Subscribe to collection

Subscribes to collection updates. When somebody updates the collection you will be notified.

 
gethttps://api.thethings.io/v2/classes/me/ID_COLLECTION?subscribe=true&keepAlive=TIME_MS
curl --request GET \
  --url 'https://api.thethings.io/v2/classes/me/ID_COLLECTION?keepAlive=TIME_MS&subscribe=true'
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/classes/me/ID_COLLECTION',
  qs: { keepAlive: 'TIME_MS', subscribe: 'true' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/classes/me/ID_COLLECTION?keepAlive=TIME_MS&subscribe=true")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/classes/me/ID_COLLECTION?keepAlive=TIME_MS&subscribe=true");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/classes/me/ID_COLLECTION"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

ID_COLLECTION
string
required
TIME_MS
int32
required
 

.

Also note that, for example, "/classes/me/:idCollection1/" is not considered to be the same collection as "/classes/me/:idCollection1/:primaryKey1/:idCollection2" , so you have to subscribe both.

curl -H "Content-Type: application/json" \
  -X GET "https://api.thethings.io/v2/classes/me/Playlists?subscribe=true&keepAlive=2000" -H
[
  {
    _id: 20,
    "name": "Classic",
    "duration" : 90
  }
]
Suggest Edits

Firmware Over-The-Air (OTA) update

thethings.iO offers Over-The-Air (OTA) firmware upgrade support to products manufacturers with minimal coding.

It permits you to distribute your firmware over Wi-Fi or mobile broadband using our API without requiring the user to connect the device to a computer via USB to perform the update, because firmware updates are available for download from the thethings.iO OTA service.

The firmware manager permits you to manage and publish your firmwares upgrades for your thing model and microcontroller unit (MCU) through the panel. The following features are available:

  1. Create and upload new firmware versions
  2. List all available versions
  3. Delete firmware versions
 
Suggest Edits

Download firmware

Download the firmware using the firmware ID (from the previous API call) and thing token.

 
gethttps://api.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID
curl --request GET \
  --url https://api.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

THING_TOKEN
string
required
FIRMWARE_ID
string
required
 
Suggest Edits

Get latest firmware version

Query for the latest firmware informations for the model of the thing corresponding to the specified thing token. It will return all latest firmware registered for every micro-controller (MCU).

 
gethttps://api.thethings.io/v2/things/THING_TOKEN/firmwares/latest
curl --request GET \
  --url https://api.thethings.io/v2/things/THING_TOKEN/firmwares/latest
var request = require("request");

var options = { method: 'GET',
  url: 'https://api.thethings.io/v2/things/THING_TOKEN/firmwares/latest' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.thethings.io/v2/things/THING_TOKEN/firmwares/latest")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.thethings.io/v2/things/THING_TOKEN/firmwares/latest");

xhr.send(data);
import requests

url = "https://api.thethings.io/v2/things/THING_TOKEN/firmwares/latest"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

THING_TOKEN
string
required
 
{
  "status": "success",
  "firmwares": [
    {
      productId: 1234,
      version: '1.0.1',
      notes: 'Wifi firmware changelog',
      _id: '56c5a331665c14fa09612f38',
      createdAt: '2016-02-18T10:55:45.517Z',
      file:
      {
        id: '56c5a331665c14fa09612f35',
        md5: '0ad066a5d29f3f2a2a1c7c17dd082a79',
        type: 'gfs',
        url: 'https://api.thethings.io/v2/models/125/firmwares/download/ey...oeZPc1raYnhDe7mLo'
      },
      targetMCU: 'WiFi'
    },
    {
      productId: 1234,
      version: '1.0.2',
      notes: 'Main board firmware changelog',
      _id: '56c5a331665c14fa09612f39',
      createdAt: '2016-02-18T10:55:45.519Z',
      file:
      {
        id: '56c5a331665c14fa09612f34',
        md5: '0ad066a5d29f3f2a2a1c7c17dd082a79',
        type: 'gfs',
        url: 'https://api.thethings.io/v2/models/125/firmwares/download/ey...ljMAXtn3snvSz0dT1Rw'
      },
      targetMCU: 'Main'
    }
  ]
}
Suggest Edits

Get latest firmware version

Query for the latest firmware informations for the model of the thing corresponding to the specified thing token. It will return all latest firmware registered for every micro-controller (MCU).

 

MQTT Request

SUBSCRIBE v2/things/THING_TOKEN/firmwares/latest/response

PUBLISH v2/things/THING_TOKEN/firmwares/latest/request

# Subscribe for the response
mosquitto_sub -h "mqtt.thethings.io" -t "v2/things/THING_TOKEN/firmwares/latest/response" -d
              
# Publish request
mosquitto_pub -h "mqtt.thethings.io" -t "v2/things/THING_TOKEN/firmwares/latest/request" -m '{"_requestId":"[randomId]"}' -d
{
  "status": "success",
  "firmwares": [
    {
      productId: 1234,
      version: '1.0.1',
      notes: 'Wifi firmware changelog',
      _id: '56c5a331665c14fa09612f38',
      createdAt: '2016-02-18T10:55:45.517Z',
      file:
      {
        id: '56c5a331665c14fa09612f35',
        md5: '0ad066a5d29f3f2a2a1c7c17dd082a79',
        type: 'gfs',
        url: 'https://api.thethings.io/v2/models/125/firmwares/download/ey...oeZPc1raYnhDe7mLo'
      },
      targetMCU: 'WiFi'
    },
    {
      productId: 1234,
      version: '1.0.2',
      notes: 'Main board firmware changelog',
      _id: '56c5a331665c14fa09612f39',
      createdAt: '2016-02-18T10:55:45.519Z',
      file:
      {
        id: '56c5a331665c14fa09612f34',
        md5: '0ad066a5d29f3f2a2a1c7c17dd082a79',
        type: 'gfs',
        url: 'https://api.thethings.io/v2/models/125/firmwares/download/ey...ljMAXtn3snvSz0dT1Rw'
      },
      targetMCU: 'Main'
    }
  ]
}
Suggest Edits

Download firmware

Download the firmware using the firmware ID (from the previous API call) and thing token.

 

MQTT Request

SUBSCRIBE v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID/response

PUBLISH v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID/request

# Subscribe for the response
mosquitto_sub -h "mqtt.thethings.io" -q 0 -t "v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID/response"
-d
          
# Publish request
mosquitto_pub -h "mqtt.thethings.io" -q 0 -t "v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID/request" -m '{"_requestId":"RAW"}' -d
Suggest Edits

CoAP Status Codes

 

The COAP API return appropriate COAP status codes for every request.

2.01

Created

2.02

Deleted

2.03

Valid

2.04

Changed

2.05

Content

4.00

Bad Request

4.01

Unauthorized

4.03

Forbidden

4.04

Not Found

4.08

Request Entity Incomplete

4.12

Precondition Failed

4.13

Request Entity Too Large

5.00

Internal Server Error

5.02

Bad Gateway

5.03

Service Unavailable

5.04

Gateway Timeout

Suggest Edits

Download firmware

Download the firmware using the firmware ID (from the previous API call) and thing token.

 

CoAP Request

GET coap://coap.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID

coap get coap://coap.thethings.io/v2/things/THING_TOKEN/firmwares/download/FIRMWARE_ID
Suggest Edits

Get latest firmware version

Query for the latest firmware informations for the model of the thing corresponding to the specified thing token. It will return all latest firmware registered for every micro-controller (MCU)

 

CoAP Request

GET coap://coap.thethings.io/v2/things/THING_TOKEN/firmwares/latest

coap get coap://coap.thethings.io/v2/things/THING_TOKEN/firmwares/latest
{
  "status": "success",
  "firmwares": [
    {
      productId: 1234,
      version: '1.0.1',
      notes: 'Wifi firmware changelog',
      _id: '56c5a331665c14fa09612f38',
      createdAt: '2016-02-18T10:55:45.517Z',
      file:
      {
        id: '56c5a331665c14fa09612f35',
        md5: '0ad066a5d29f3f2a2a1c7c17dd082a79',
        type: 'gfs',
        url: 'https://api.thethings.io/v2/models/125/firmwares/download/ey...oeZPc1raYnhDe7mLo'
      },
      targetMCU: 'WiFi'
    },
    {
      productId: 1234,
      version: '1.0.2',
      notes: 'Main board firmware changelog',
      _id: '56c5a331665c14fa09612f39',
      createdAt: '2016-02-18T10:55:45.519Z',
      file:
      {
        id: '56c5a331665c14fa09612f34',
        md5: '0ad066a5d29f3f2a2a1c7c17dd082a79',
        type: 'gfs',
        url: 'https://api.thethings.io/v2/models/125/firmwares/download/ey...ljMAXtn3snvSz0dT1Rw'
      },
      targetMCU: 'Main'
    }
  ]
}