These docs are for v2.0. Click to read the latest docs for v3.3.

App Development

This document is a guide to understand how to create apps on top of Internet of Things using our Platform.

📘

Before you start learning how to use our platform to connect your devices, we recommend that you read first our Getting Started guide in order to create your Account and set up the platform.

👍

In this guide, we only show the basics of the API REST. You can access to the full REST API Reference to get the full list of endpoints available and play with them from the docs.

Getting started

Apps are intended to use the HTTP API REST to work with our Platform. You can also subscribe for realtime updates using Websockets with Socket.io.

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 these 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 does not only have to be a string or a number. It can be an array, a JSON object or even a binary.

HTTPS is a layer on 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 vs HTTPS

HTTP calls (without SSL support) are not allowed for App Development.

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. 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 your APP will ask for. These resources must match with the public resources defined on your product.
Product resources remain private and inaccessible by the APPs until you explicitly define them as public.

Postman test

Postman collection

You can test the following examples importing this postman collection: APP Development Postman Collection

Get Postman: Postman REST Client.

Curl Test

This is thethings.iO CURL test to check that you are able to make requests.

curl -H "Content-Type: application/json" \
  -X GET "https://api.thethings.io/v2/"
# That is ok. This is the response that you have to get.
{
  "status": "error",
  "code": 401,
  "message": "Invalid session token"
}

Session Token

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. It will let our Platform 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.

REST API Basics for App Development

🚧

In the next examples, you have to replace the variables inside brackets {{SESSION TOKEN}}. The brackets include your actual value.

Register

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

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"email": "YOUR EMAIL HERE", "password": "a hard to guess password", "app": "The appID given in the panel"}' \
  -X POST "https://api.thethings.io/v2/register" -k
{
  "token": "5w3iea4uCCNPkLNkm6R6OpyOPXo",
  "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"
}

Login

Log in an App user at thethings.iO Platform. This returns the session token and roles. Roles identifies the resources and things that the user has authorized the App to access.

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"email": "YOUR EMAIL HERE", "password": "a hard to guess password", "app": "The appID given in the panel"}' \
  -X POST "https://api.thethings.io/v2/login" -k
{
  "token": "5w3iea4uCCNPkLNkm6R6OpyOPXo",
  "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
      }
    }
  }
}

Activate

If you didn't activate a thing, go to the Getting Started guide and activate at least one to get the Thing Token.

Link Thing

Before getting the user's data from a thing, it is necessary to do 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. 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 thing 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).

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -d '{"thingToken": "{ {thingToken} }"}' \
  -X POST "https://api.thethings.io/v2/me/things" -k
{
  "status": "success",
  "message": "created",
  "thingId": "01234_567890-0abcde_fghi-jklm_nopqrs-tuvxyz"
}

📘

Examples

You can find more detailed information about Link Thing prodedures at How to link a Thing Guide.

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 the resources.

To check which resources has the user available we can call the GET /resources endpoint. The permissions are granted automatically. 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 the permission to more users.

Get User Resources

Get the user's resources and the things associated to each resource. If the user didn't link a thing, the response will be empty.

curl -i -H "Accept: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -X GET "https://api.thethings.io/v2/me/resources" -k
# 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", ...]
  },
  ...
]

Sharing resources with Grant

When a user wants to give access of 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.

In the next example, we let the user’s friend read the thingId1’s temperature. He/she won’t be able to grant this resource to anybody else as we aren’t granting him/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": "[email protected]", permissions": {"temperature":{"thingId1":{"get": true}}}}' \
  -X PUT "https://api.thethings.io/v2/me/grant" -k
{
  status: 'success',
  message: 'granted'
}

Get resource values

This endpoint returns the values of the specified resource.

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"}
  ]
}

Query parameters

ParameterDefaultFormatDescription
limit1NumberHow many results (max 1000)
startDateJan 1st 1970YYYYMMDDHHmmssThe min date
endDateEnd of times (for JavaScript)YYYYMMDDHHmmssThe max date

The maximum number of values that would be returned are the last 1000. So if you need to get more than 1000 values, you have to query the previous 1000 values using the endDate of the last value returned by the first query.

In the next example we want to get 2300 values of the resource temperature:

curl -i -H "Accept: application/json" \
  -X GET "https://api.thethings.io/v2/me/resources/{{KEY}}/{{THING_ID}}?limit=1000" -k
[
 // 1
    {
        "key": "temperature",
        "value": 24.311,
        "datetime": "2017-01-16T10:25:10.644Z"
    },
  // 2
    {
        "key": "temperature",
        "value": 47.953,
        "datetime": "2017-01-16T10:24:10.641Z"
    },
   // 3
    {
        "key": "temperature",
        "value": 29.241,
        "datetime": "2017-01-16T10:23:10.677Z"
    },
  
  // ..........
  
  // The next value has the datetime that you need to use as a endDate at   
  // the next query
  
  // 1000

    {
        "key": "temperature",
        "value": 22.958,
        "datetime": "2017-01-15T17:46:06.932Z"
    }
]
curl -i -H "Accept: application/json" \
  -X GET "https://api.thethings.io/v2/me/resources/{{KEY}}/{{THING_ID}}?limit=1000&endDate=2017-01-15T17:46:06.932Z" -k
[
  // 1
    {
        "key": "temperature",
        "value": 53.708,
        "datetime": "2017-01-15T17:45:06.929Z"
    },
  
  // 2
    {
        "key": "temperature",
        "value": 41.794,
        "datetime": "2017-01-15T17:44:06.966Z"
    },
  
  // 3
    {
        "key": "temperature",
        "value": 47.891,
        "datetime": "2017-01-15T17:43:06.920Z"
    },
  
  // ........
  
  // Again, the next value has the datetime that you need to use as a endDate at  
  // the next query
  
  // 1000
    {
        "key": "temperature",
        "value": 24.805999999999997,
        "datetime": "2017-01-15T01:06:03.212Z"
    }
]
curl -i -H "Accept: application/json" \
  -X GET "https://api.thethings.io/v2/me/resources/{{KEY}}/{{THING_ID}}?limit=1000&endDate=2017-01-15T01:06:03.212Z" -k
[
  // 1
    {
        "key": "temperature",
        "value": 48.681,
        "datetime": "2017-01-15T01:05:03.137Z"
    },
  
  // 2
    {
        "key": "temperature",
        "value": 14.525,
        "datetime": "2017-01-15T01:04:03.132Z"
    },
  
  // 3
    {
        "key": "temperature",
        "value": 25.47,
        "datetime": "2017-01-15T01:03:03.129Z"
    },
  
  // ........
  
  // 300
  
      {
        "key": "temperature",
        "value": 31.622,
        "datetime": "2017-01-14T08:25:59.695Z"
    }
]

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 is expired, you 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 Websockets. REST API subscription is not reliable on browsers.

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -d '{"thingToken": "{ {thingToken} }"}' \
  -X POST "https://api.thethings.io/v2/me/things" -k
[
  {
    "value":15,
    "id": "thingId1"
  }
]

Post resource values

This endpoint stores the values at the resource specified.

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -d '{"values": [{"value": 15}] }' \
  -X POST "https://api.thethings.io/v2/me/resources/temperature/{ {thingId} }" -k
# Everything has gone well
{
  "status": "Success",
  "message": "Created"
}

Query parameters

ParameterDefaultFormatDescription
storetrueBooleanIf false, it will broadcast a value but NOT store the value.
broadcasttrueBooleanIf false, it will store the value WITHOUT broadcasting to the subscribers.

Magic resources

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

🚧

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

$geo resource

This resource allows updates and retrieves the current thing position in GeoJSON format. The coordinates order is longitude and then latitude [longitude, latitude].

curl -i -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -d '{"values": [{"value": {"type": "Point","coordinates": [2.154007, 41.390205]}}] }' \
  -X POST 'https://api.thethings.io/v2/me/resources/$geo/{{thingId}}' -k
// Everything is ok
{"status":"created"}
curl -i -H "Accept: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -X GET 'https://api.thethings.io/v2/me/resources/$geo/{{thingId}}' -k
// On success, the GET command returns JSON structured like this
[{"key":"$geo","value":{"type":"Point","coordinates":[2.154007,41.390205]}}]

$settings resource

This resource allows updates and retrieves things settings meta-data store. It also permits to get and set a single value in the path (in dot notation).

curl -H "Content-Type: application/json" \
       -d '{"values":
      [{
          "value" : {
                  "name": "My Thing",
                  "foo": "bar"
          }
       }]
  }' \
       -X POST "https://api.thethings.io/v2/me/resources/$settings/{{thingId}}"
curl -H "Content-Type: application/json" \
       -d '{"values":
      [{
          "value" : "My Thing"
       }]
  }' \
       -X POST "https://api.thethings.io/v2/me/resources/$settings.name/{{thingId}}"
// Everything is ok
{"status":"created"}
curl -i -H "Accept: application/json" \
  -X GET 'https://api.thethings.io/v2/me/resources/$settings/{{thingId}}' \
  -k
curl -i -H "Accept: application/json" \
  -X GET 'https://api.thethings.io/v2/me/resources/$settings.name/{{thingId}}' \
  -k
// GET settings
[{"key":"$settings","value":{"name":"My Thing","foo":"bar"}}]

// GET settings value name
[{"key":"$settings.name","value":"My Thing"}]

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 App user’s password.

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
{
  status: 'success',
  message: 'updated'
}

Get settings

Retrieve the settings object.

curl -i -H "Accept: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -X GET "https://api.thethings.io/v2/me/settings" -k
{
  "hair-color" : "pink",
  "phones" : ["123456", "998965"]
}

Get Server Date

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

curl -i -H "Accept: application/json" \
  -H "Authorization: { {SESSION TOKEN} }" \
  -X GET "https://api.thethings.io/v2/utils/date/?format=UTC" -k
{
  "date": "2016-03-15T14:14:09.051Z",
  "values": [
    {
      "value": "2016-03-15T14:14:09.051Z"
    }
  ]
}

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 to 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.

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
{
  "status": "success",
  "message":"created",
  "id":"25"
}

You can set the _id at the path, too.

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

Delete an object

Delete an object by _id.

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
{
  "status": "success",
  "message": "deleted"
}

Update an object

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

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
{
  status: 'success',
  message: 'updated'
}

Get Object

Returns the object stored with this key.

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
    }
  ]
}

Get Collection of objects

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

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
    }
  ]
}

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.

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
  }
]

Object relations

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

/classes/me/Playlists/25/Songs/100/

Ternary relations:

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

However the routes are not equivalent, because the ordering matters:

/classes/me/Songs/100/Playlist/25 != /classes/me/Songs/100/Playlist/25/Artist/10

Note that doing:

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

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