Developing IoT Apps with thethings.iO

This document is a guide to understand how to create apps on top of Internet of Things using thethings.iO. It's recommendable to read the Quickstart guide first to, at least, create an account and activate a thing.

Getting started

Apps are intended to use the HTTP API REST to work with thethings.iO Platform. Complete API Reference.

Postman collection

You can test the following examples importing this postman collection: thethings.iO APP Dev Postman Collection

Get Postman: Postman REST Client.

Things and Resources

The Things are the virtual representations of your Internet-connected devices.

We can see a Thing connected to the Internet as a collection of Resources. And each Resource can be seen as a timeline.

The thing is going to publish or consume this resources. For example, a thing with a temperature sensor is going to publish temperature and a thing that is an on-off switch is going to consume a resource called turn which can take values on or off.

Everything can be a resource
The value of a resource has not only to be a string or a number it can be an array, a json object or even a binary.

Security and Authentication

HTTPS is a layer on the top of HTTP with SSL/TLS protocol that provides authentication and bidirectional communications encryption that protects from man-in-the-middle attacks, eavesdropping and tampering.

HTTP calls (without SSL support) are not allowed..

Making an IoT App

Once you understand the concepts of Thing and Resource, you can start to analyze the requirements of your application.

You must choose a set of resources (it is possible to edit them later) that your app will be using. The possibilities are limitless. For example, you can choose temperature and humidity. Another option would be to choose steps and calories, so the application will be compatible with all the things publishing steps and/or calories (Fitbit, nikeplus,...) connected to the platform. Or maybe an application to control the energy consumption of a home using the resource power-consumption.

You can register an app from the Panel. Once registered you will get an appID to identify your app.

At the same Panel you have to configure which resources will ask your APP for. This resources must match with the public resources defined on your product. Product resources remain private and unnaccesible by the APPs until you explicitly define them as public. You can follow the instructions at this page (Create a new IoT Product and Create a new IoT App sections): Premium Panel.


The first thing you need to do is to send the username, password and appID to register the user, then log the user in so you can get a session token.

This session token is necessary to be sent in the header Authorization in every call to the platform from now on. And will let thethings.iO to identify the user and the application. This session token also contains the list of things and resources the user has authorized the app to access.


Register an App user at thethings.iO Platform. This endpoint also login the user (returns the session token and roles), so you don't have to do another api call to login him.



Login an App user at thethings.iO Platform. Returns the session token and roles. Roles identifies the resources and things that the user has authorized the App to access.



If you didn't activated a thing, go to the Quickstart guide, and activate at least one.

Link Thing

Before getting the user's data from a thing, it is necessary a procedure called link thing which allows the platform to know that the user is the owner of the thing.

This procedure needs a thingToken (or the thingId) and a session token. And it requires some kind of direct communication between the app and the thing. For example, when setting up the wifi for the thing and the ssid and password are sent to the thing, it’s a good moment to ask for the thingToken of the thing. With this thingToken, the App will be able to do the REST call to link the think to the user and store the relation at the platform.
Note that in order to link the thing the user must be logged in and the thing must be activated (i.e. have a thingToken)

This operation can only be done for applications which have been authorized for the thing developer, this kind of apps are called official apps.


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 this 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 asks 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 application can access the data. There is an exception, when the app is an official app the permissions are granted automatically.

Get Resources

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



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


Sharing resources

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

At the next example, we let the user’s friend to read the thingId1’s temperature. 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.


Get resource values

This endpoint returns the values of the specified resource.

GET{ {resource} }

Request Parameters

Parameter Default Format Description
limit 1 Number How many results (max 100)
startDate Jan 1st 1970 YYYYMMDDHHmmss The min date
endDate End of times (for JavaScript) YYYYMMDDHHmmss The max date

Get all resources values

This endpoint returns the last(s) values of all the resources.

GET{ {thingId} }

Request Parameters

Parameter Default Format Description
limit 1 Number How many results (max 100)
startDate Jan 1st 1970 YYYYMMDDHHmmss The min date
endDate End of times (for JavaScript) YYYYMMDDHHmmss The max date

Subscribe to resource values

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

If there are no updates the server will send {} after keepAlive ms. You should also keep a timer, and if you don’t receive updates after keepAlive time isexpired, yo have to resubscribe. This could happen if the wifi 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.

GET{ {resource} }?subscribe=true&keepAlive={ {time_ms} }

Post resource values

Once the app has received permission to write the resource, we could do this query to push data to the resource. This requirement don't apply to official apps.

POST{ {thingId} }

Thing's description

There’s a special resource called description that can contain meta-data about the thing. This meta-data could be the Thing name (chosen by the user), geocoordinates, JSON objects and any other data the developer want to put there.

This resource is accesible the same way that all the resources. With the get and put resource values.

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

PUT https ://{ {thingId} }

User's settings

Sometimes the app needs to store additional data about the user (gender, avatar, hair color,...) 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.

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

Update settings

Updates the settings key/value object.

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


Get settings

Retrieve the settings object.


Get Server Date

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

GET https ://

Objects. Storing App data.

When the application needs to store objects more complex than the key-value settings it can use the endpoint /classes/
This endpoint is highly flexible storing 1 - N relationships. And with a few tricks it’s possible to represent more complex relations.

The endpoint divide in two paths. /classes/me/ and /classes/app/*. The first one is only accessible by the user who stored the object. The second one allows any app user to retrieve the data. You must add the authorization header with the session token in all the calls. From now on, /me is equivalent to /app

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.

POST{ {idCollection} }

You can set the _id at the path, too.

POST{ {idCollection} }/{ {primaryKey} }

Delete an object

Delete an object by _id.

DELETE{ {idCollection} }/{ {primaryKey} }

Update an object

Change the values from an object. If there are some values which are not overwritten, this values won’t be deleted.

PUT{ {idCollection} }/{ {primaryKey} }

Get Object

Returns the object stored with this key.

GET{ {idCollection} }/{ {primaryKey} }

Get Collection of objects

Returns all the collection's objects ordered by primary key descending.

GET{ {idCollection} }

Subscribe to collection

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

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

GET{ {idCollection} }?subscribe=true&keepAlive={ {time_ms} }

Object relations

It is possible to add more path segments in these queries to be able to represent 1 - N binary relations, example:


or ternary relations

/classes/me/Playlists/25/Songs/100/Artist/10/ ...

However that routes are not equivalent to:

/classes/me/Songs/100/Playlist/25   or  /classes/me/Songs/100/Playlist/25/Artist/10

So, the ordering matters.

Note that doing:

POST /classes/me/:idCollection1/:primaryKey1/:idCollection2/:primaryKey2/

without creating :primarykey1 will not return error and will work, but then you should remember somehow :primaryKey1