FORMAT: 1A HOST: https://m.thingscale.io/v2/ # ThingScale API Explorer In this chapter, we describe the basic matters required when to use the API. >Please be aware that if you use the production API key in this sandbox all will be executed ## Using API ThingScale RESTful API is implemented as JSON over HTTP requests verbs GET/POST/PUT/DELETE. Currently, APIs are provided below. ## API versioning API version is specified in endpoint URI.(e.g. https://m.thingscale.io/v2/) Current API version and reference are here API Reference (V2.0.0) ## Security All communication with ThingScale is performed over https(HTTP over TLS). This ensures that all communication between ThingScale and device is over an encrypted communication. HTTP/MQTT device connector can use plain-http and non-encrypted TCP communication for small memory footprint MCUs.(MCU:Micro Control Unit) HTTP/HTTPS both protocols have pros and cons, choosing the right one depend on your environment and security trade-off.
>We STRONGLY RECOMMENDED HTTPS/MQTTS for secure connection.
ProtocolSecurityResource requirement for MCUs
HTTP/MQTTPoor(Non-encryption)Low
HTTPS/MQTTSExcellent(Avoid men-in-middle attack)High(Use more memory and CPU cycles..)
## Token Tokens are per-user unique authorize key for API/Device connector. In all cases you want to use the API token, it is strongly recommended that you use the HTTPS(TLS) connection. >NOTE
Device token is not per-device, per-user. Reason as in order to reduce the configuration task at the time of device distribution. ## Data-format and timestamps All API requests and responses use the JSON payloads only. HTTP and MQTT device connector use the URL Encodeded payloads. All timestamps are relative to UTC.Timestamps format is ISO8601:2004 standard. NOTE
when stream retrieve,time range specified local timezone.(e.g. 'YYYY-MM-DD hh:mm') ## API rate limit API usage is rate limited by per-second API request numbers. The device connector rate limit by per-minutes request numbers. >NOTE
If the connection count has reached the upper limit,then API returns 429 Too Many Requests HTTP status code. ## Channel Channel is a logical channel that stores the data transmitted from the device. It is not to specify the channel directly from the device, you will be distributed from the device_id(device's serial). Channel is a timeseries database with schema less JSON objects, each stream can be specified labels and units. ## Stream Stream is datapoints that send device's sensor data.(e.g. temperature) Stream has numeric(integer or float) or alphanumeric(like RFID UID) value. Data type is determine by platform side. >NOTE
alphanumeric value MUST BE ENCODE UTF-8. ## Device Device means the WSN gateway or end device. The device basically manually activated, but it is also possible to activate automatically. Requires there to map the device to the channel in any case. ## Release note Please refer ThingScale API Release note ## Device Connector Please refer Using Device Connector # Data Structure ## NOAUTH + error: `NO_AUTH` (string, required) - Auth Required. ## Device Service [/device/{device_id}] Device service manages the device registry of ThingScale, aggregates information about all of the devices. Each device accumulates the time series data to have been created by the channel (see Channel service). When the access of time series data, use Stream service(see Stream service). ### List All Devices [GET] + Parameters + device_id (string) The ID of the device. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) + Attributes (object) + device_id (string) - id of the device + description (string) - description of device + enabled (boolean) - device status + mapped_ch (number) - device related channel-Id + device_type (string) - type of device + location (string) - location of device + manufacturer (string) - manufacturer of device + body [ { "device_id": "1085266243", "description": "sht-25", "enabled": true, "mapped_ch": 0, "device_type": "Xbee Pro", "location": "Niigata,Japan", "manufacturer": "sensincs,llc", "activate_at": "2015-01-13 16:58:00" } ] + Response 401 (application/json) { "error": "AUTH_REQUIRED" } + Response 404 (application/json) { "error": "NO_DEVICE" } ### Create a New Device [POST] + Parameters + device_id (string) The ID of the device. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 201 (application/json) OK // created. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "MAX_DEVICE_REACH" } // Per account device limit reached. { "error": "DEVICE_INUSE" } // Because the same channel as the specified ID exists, it could not be created. ### Update a Device [PUT] + Parameters + device_id (string) The ID of the device. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Attributes (object) + description (string, required) - device description + enabled (boolean) - device status + mapped_ch (number) - device related channel-Id + device_type (string) - type of device + location (string) - location of device + manufacturer (string) - manufacturer of device + body { "description" : "DEVICE_DESCRIPTION", "enabled" : "DEVICE_STATUS", // true or false "mapped_ch" : MAP_CHANNEL_NUMBER, // integer "device_type" : "DEVICE_TYPE", "location" : "DEVICE_LOCATION", "manufacturer" : "DEVICE_MANUFACTURER" } + Response 200 (application/json) OK + Response 400 (application/json) + body { "error": "BAD_JSON_FORMAT" } // check json array + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "NO_CHANNEL" } // Because channel_id is nothing or already exist + Response 404 (application/json) + body { "error": "NO_DEVICE" } // Specified device_id is not found. ### Delete a Device [DELETE] + Parameters + device_id (string) The ID of the device. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "DEVICE_ENABLE" } // Specified device status is enable. + Response 404 (application/json) + body { "error": "NO_DEVICE" } // Specified device_id is not found. ## Channel Service [/channel/{channel_id}] Channel service is accessing for time series data storage channel management when it is associated with the device. To access the stream data stored in the channel, use Stream service(see Stream service). ### List All channels [GET]
Special HeaderDescription
X-WITHTAG (boolean) show tags with channel
>(NOTE)
Tag name is created when you want to put data containing tags in the channel. + Parameters + channel_id (integer) The ID of the channel. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) + Attributes (object) + channel (number) - channel-Id + tag (string) - tag name + channel_name (string) - channel description + last_update (string) - last update time + body [ { "channel": 0, "tag": "node1", "channel_name": "Sensinics 7F", "last_update" : "2015-05-10T21:24:50+0900" } ] + Response 401 (application/json) { "error": "AUTH_REQUIRED" } + Response 404 (application/json) { "error": "NO_CHANNEL" } ### Create a New Channel [POST] + Parameters + channel_id (integer) The ID of the channel. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 201 (application/json) OK // created. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "CHANNEL_INUSE" } // Because the same channel as the specified ID exists, it could not be created. + Response 404 (application/json) + body { "error": "NO_CHANNEL" } ### Update a Channel [PUT]
Special HeaderDescription
X-TAGNAME (string) tagname as string
>(NOTE)
Tag name is created when you want to put data containing tags in the channel. + Parameters + channel_id (integer) The ID of the channel. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Attributes (object) + channel (number) - channel-Id + tag (string) - tag name + channel_name (string) - channel description + last_update (string) - last update time + body [ { "channel": 0, "tag": "node1", "channel_name": "Sensinics 7F", "last_update" : "2015-05-10T21:24:50+0900" } ] + Response 200 (application/json) OK // updated. + Response 400 (application/json) + body { "error": "BAD_JSON_FORMAT" } // check json array. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 404 (application/json) + body { "error": "NO_CHANNEL" } ### Delete a Channel [DELETE]
Special HeaderDescription
X-TAGNAME (string) tagname as string
>(NOTE)
Tag name is created when you want to put data containing tags in the channel. + Parameters + channel_id (integer) The ID of the channel. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) OK // deleted. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "CHANNEL_INUSE" } // Specified channel is used by device. + Response 404 (application/json) + body { "error": "NO_CHANNEL" } // Specified channel is used by device. ## Stream Service [/stream/{channel_id}] Stream service provides access to time-series data that has been accumulated in the channel. Before you can use the Stream service, you must have completed the following steps.
  1. Creating a new device that generates a stream (see: Stream service)
  2. Create a new channel that contains a stream (see: Channel service)
  3. Device and channel association (see: Device service)
### Retrieve streams [GET]
Special HeaderDescription
X-TAGNAME (string) tagname as string
X-STARTTIME (string) time range as start // YYYY-MM-DD hh:ss or last
X-ENDTIME (string,required) time range as end // YYYY-MM-DD hh:ss or last
X-PAGELIMIT (string) rows per page // default as 1
X-PAGESORT (string) desc or asc // default as asc
X-AGGREGATE (string) Aggregate Mode option // avg,sum,min,max
>(NOTE)
1)X-PAGELIMIT effective when X-ENDTIME:last use.
2)starttime and endtime are must be specified at local time.
3)X-ENDTIME:last is not affected in Aggregate Mode. + Parameters + channel_id (integer) The ID of the channel. + Request + Headers X-APITOKEN : APITOKEN X-ENDTIME : last + Response 200 (application/json) + Attributes (object) + channel (number) - channel-Id + channel_name (string) - channel description + last_update (string) - last update time + stream (object) + id (number) - object id + tag (string) - tag name + value (object) - JSON payload // (NOTE)binary message is HEX encoded + at (string) - timestamp ISO8601 + body // normal { "channel": 0, "channel_name": "sensor_1", "last_update": "2016-11-18T19:07:02+0900", "stream": [ { "_id": "582ed2c66807f4e702de3d87", "tag" : null, "value": { "temp": 20, "humid": 50, "rssi": 80, "vbat": 95 }, "at": "2016-11-18T19:07:02+0900" } ] } // Aggregate Mode (Use with X-AGGREGATE) { "channel": 0, "channel_name": "sensor_1", "last_update": "2016-11-18T19:07:02+0900", "aggr_type": "min", "result": [ { "_id": null, "value": 24.8 // min } ] } + Response 401 (application/json) { "error": "AUTH_REQUIRED" } + Response 404 (application/json) { "error": "NO_CHANNEL" } // The specified channel does not exist. { "error": "NO_DATA" } // No datapoints exist in specified time range. + Response 500 (application/json) { "error": "AGGR_ERROR" } // Some internal error occurred in Aggregate Mode. { "error" : "NOSQL_ERROR"} // NoSQL error occured. { "error" : "NOSQL_TIMEOUT"} // NoSQL read timeout occured. ## Stream Service * write_only * [/stream/] Stream service provides access to time-series data that has been accumulated in the channel. Before you can use the Stream service, you must have completed the following steps.
  1. Creating a new device that generates a stream (see: Stream service)
  2. Create a new channel that contains a stream (see: Channel service)
  3. Device and channel association (see: Device service)
### Write streams [POST] + Request + Headers X-DEVICETOKEN : DEVICE_TOKEN + Attributes (object) + stream (object) + serial (string, required) // device id + value (object) - JSON payload or numeric value + body { "stream" : [ { "serial" : "1085266243new22", // DEVICE_ID "value" : 12 } // Multiple Write { "serial" : "1085266243new32", "value" : "ID000004556AEE" } // ] } + Response 200 (application/json) OK // transaction ok. + Response 201 (application/json) Created // new device created. + Response 400 (application/json) + body { "error": "DEVICE_ID_ZERO" } // deivce_id:0 is not allowed.(or device_id:NULL) + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "NO_MAPPED_CH" } // Sender device's serial number is not map to channel. { "error": "DEVICE_DISABLED" } // Devices status is disabled. + Response 500 (application/json) { "error" : "NOSQL_ERROR"} // NoSQL error occured. ## Event Service [/event/{event_id}] Event service is by setting a threshold for the stream of the channel, make the notification to the email or an external system. Before Event service use, please make sure that the stream to the channel is stored. ### List events [GET] + Parameters + event_id (integer) The ID of the event. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) + Attributes (object) + event_id (number) - event-Id + mapped_ch (number) - event related channel-Id + description (string) - description of event + notify_type : "email" or "http" (string) - notification method + post_url (string) - webhook URI + enabled (boolean) - event status + source (string) - target payload of channel // eg1.{"temp":25} → temp eg2.{"data":[{"value" : 10}]} →data:value + operator (string) - "<" : IF source < threshold ">" : IF source > threshold "<=" : IF source <= threshold ">=" : IF source >= threshold "=" : IF source = threshold "!=" : IF source != threshold + threshold (string) - threshold value + body [ { "event_id": 1, "mapped_ch": 0, "description": "CH0 Low TEMP", "notify_type": "email", "post_url": "", "enabled": true, "source": "temp", "operator": "<=", "threshold": "8" } ] + Response 401 (application/json) { "error": "AUTH_REQUIRED" } + Response 404 (application/json) { "error": "NO_EVENT" } ### Update an Event [PUT] + Parameters + event_id (integer) The ID of the event. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Attributes (object) + event_id (number) - event-Id + mapped_ch (number) - event related channel-Id + description (string) - description of event + notify_type : "email" or "http" (string) - notification method + post_url (string) - webhook URI + enabled (boolean) - event status + source (string) - target payload of channel // eg1.{"temp":25} => temp eg2.{"data":[{"value" : 10}]} => data:value + operator (string) - "<" : IF source < threshold ">" : IF source > threshold "<=" : IF source <= threshold ">=" : IF source >= threshold "=" : IF source = threshold "!=" : IF source != threshold + threshold (string) - threshold value + body [ { "event_id": 1, "mapped_ch": 0, "description": "CH0 Low TEMP", "notify_type": "email", "post_url": "", "enabled": true, "source": "temp", "operator": "<=", "threshold": "8" } ] + Response 200 (application/json) OK // updated. + Response 400 (application/json) + body { "error": "BAD_JSON_FORMAT" } // check json array. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "NO_CHANNEL" } // Because channel_id is nothing + Response 404 (application/json) + body { "error": "NO_EVENT" } // Specified event_id is not found. ### Delete an Event [DELETE] + Parameters + event_id (integer) The ID of the event. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) OK // deleted. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "EVENT_ENABLE" } // Specified event status is true. + Response 404 (application/json) + body { "error": "NO_EVENT" } // Specified event_id is not found. ## Event Service * create_only * [/event/] ### Create a New Event [POST] + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 201 (application/json) {"event_id" : CREATED_EVENT_ID} + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 403 (application/json) + body { "error": "MAX_EVENT_REACH" } // Per account event limit reached. ## User Service [/user/] User service provides the management functions of the user profile. ### Retrieve user information [GET] + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) + Attributes (object) + user_id (string) - user ID + api_token (string) - API TOKEN + device_token (string) - DEVICE TOKEN + email1 (string) - email 1 of 2 + email2 (string) - email 2 of 2 + organization (string) - organization name + locale (string) - your locale + user_alias (string) - alias of user account + storage (object) + count (number) - total records of all channels + usage_bytes (number) - usage of storage + maxSize (number) - maxSize of storage + avg_obj_size (number) - average of object size + body [ { "user_id": "xxxxxxxxxxxx", "api_token": "xxxxxxxxxxxx", "device_token": "xxxxxxxxxxxx", "email1": "name@example.com", "email2": "name2@example.com", "organization": "Sensinics,LLC", "locale": "Asia/Tokyo", "user_alias": "Toru Murasawa", "storage": { "count": 10, "usage_bytes": 36864, "maxSize": 5242880000, "avg_obj_size": 97 } } ] + Response 401 (application/json) { "error": "AUTH_REQUIRED" } ### Update a User information [PUT] + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Attributes (object) + email1 (string) - email 1 of 2 + email2 (string) - email 2 of 2 + organization (string) - organization name + locale (string) - your locale + user_alias (string) - alias of user account + body { "email1": "YOUR_EMAIL_ADDRESS1", "email2": "YOUR_EMAIL_ADDRESS2", "organization": "YOUR_ORGANIZATION", "locale": "YOUR_LOCALE(TIMEZONE)", // e.g. Asia/Tokyo (set from Management Console recommended.) "user_alias": "YOUR_NAME" } + Response 200 (application/json) OK // updated. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } ## Publish Service [/publish/{device_id}] Publish service provides message delivery function to the device from ThingScale.
By Publish service, it will deliver the command to the device that are subscribed to the MQTT broker of ThingScale. Destination MQTT Topic
TopicPayload
[device_token]/[device_id]/subscribecontents of "payload"
>(NOTE)
Messages that are commonly published to the device includes a control command . >(About MQTT Topic/message)
In the Publish Service, device token corresponding to the device ID is published embedded in MQTT topic.
On the device side, it is possible to receive a message from the Publish Service by to subscribe to MQTT broker ThingScale the following topics.
Message (payload) Please specify in the freestyle.(ThingScale does not concern the content of the payload.) >(About Destination Device)
Device that receives the message, prior to the device API: You must have been registered at (see Device service list).
In fact MQTT publish API returns an error if the ThingScale device registry is wrong if the device ID does not exist will not be performed. ### Publish message [POST] + Parameters + device_id (string) The ID of the device. + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) OK // published. + Response 400 (application/json) + body { "error": "BAD_JSON_FORMAT" } // check json array. + Response 401 (application/json) + body { "error": "AUTH_REQUIRED" } + Response 404 (application/json) + body { "error": "NO_DEVICE" } ## Session Service [/session] Session service provides showing pub/sub status to ThingScale's built-in message broker.
Both MQTT and WebSocket clients shown in session. >(About how to see the session)
If Publish from the device to the message broker is not a persistent session and disconnects the payload every time it is sent out, the session will be terminated in a very short period of time, so it is not possible to catch the session in most cases.
When a device subscribes to a message broker, it is inevitably a persistent session so it can be caught until the session ends. ### List active sessions [GET] + Request + Headers X-APITOKEN : YOUR_API_TOKEN + Response 200 (application/json) + Attributes (object) + cliend_id (string) - MQTT clientid + ipaddress (string) - Client's IP address + clean_sess (boolean) - MQTT clean session capability + proto_ver (number) - MQTT protocol version + keepalive (number) - MQTT keepalive timer + connected_at (string) - pub/sub connection initiate time(ISO8601) + body [ { "client_id": "mosqsub/14968-stg.testclient", "ipaddress": "XXX.XXX.XXX.XXX", "clean_sess": true, "proto_ver": 3, "keepalive": 60, "connected_at": "2017-10-22T16:28:39+0900" } [ + Response 401 (application/json) { "error": "AUTH_REQUIRED" }