Overview
The macchina.io REMOTE server provides a REST API for programmatically querying and modifying device meta information. Using the API you can get a list of devices, search for a device, get and modify device properties, create and delete devices.
Endpoint
The HTTP or HTTPS endpoint for all API requests is remote.macchina.io. We highly recommend using HTTPS, especially if sensitive data like usernames and passwords are transmitted. This is especially true if HTTP Basic Authentication is used.
Authentication
The API supports three authentication mechanisms. The first is HTTP Basic Authentication (over HTTPS), the second one is session-based authentication, and the third one is bearer token-based authentication.
HTTP Basic Authentication
For HTTP Basic authentication, the username and password must be supplied in the Authorization header with every HTTP request.
Note: all following examples use username "user" and password "s3cr3t".
Following is an example for a request using Basic Authentication:
GET /my-devices/api/devices HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Session-Based Authentication
The second authentication mechanism is session-based authentication. This uses a session cookie, which must be passed with every request, along with a XSRF (CSRF) token to prevent cross-site request forgery attacks. To obtain valid session and XSRF token cookies, a Login request must be sent to theserver. This is a POST request to the server root ("/"), with the username and password supplied as form-encoded parameters in the request body.
POST / HTTP/1.1
Host: remote.macchina.io
Connection: Close
Content-Length: 42
Content-Type: application/x-www-form-urlencoded
action=login&username=user&password=s3cr3t
The following parameters must be given:
- action: This must always have the value login.
- username: The name of the user.
- password: The user's password.
Instead of a username and password, a JSON Web Token (JWT) can be used for authenticating the user. The JWT is passed in a parameter named jwt. See below for how to obtain the token from the server.
Additionally, the following optional parameters can be passed:
- onsuccess: The URI of a page to redirect to if the login was successful. If this is given and authentication was successful, the response will have a 303 See Other status with a Location header containing the URI given here.
- onfailure: Similar to onsuccess, the URI given here will be used if authentication failed.
If onsuccess and onfailure are not given, the response status will be 200 OK if authentication succeeded, or 401 Unauthorized if authentication failed.
If onsuccess or onfailure contain URLs pointing to external web servers, these URLs must be whitelisted in the macchina.io REMOTE server configuration file.
If authentication was successful, the response will include Set-Cookie headers containing the session cookie (osp.web.session.my-devices) and XSRF token (XSRF-TOKEN). This session cookie and XSRF token must be passed in with all API requests. The XSRF token must be passed in the X-XSRF-TOKEN request header.
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 10:35:30 GMT
Set-Cookie: osp.web.session.my-devices=a75fece1fc6d045049d7e1c832ddb1550c002e67;
domain=.remote.macchina.io;
path=/;
HttpOnly;
expires=Thu, 01 Mar 2012 12:35:30 GMT
Set-Cookie: XSRF-TOKEN=6c7b5b839425b23359d38a8082a73858b68c478e;
path=/;
expires=Thu, 01 Mar 2012 12:35:30 GMT
Here is an example for using the session cookie and XSRF token in a REST request:
GET /my-devices/api/devices HTTP/1.1
Host: remote.macchina.io
Cookie: osp.web.session.my-devices=a75fece1fc6d045049d7e1c832ddb1550c002e67
X-XSRF-TOKEN: 6c7b5b839425b23359d38a8082a73858b68c478e
Connection: Close
Bearer Token-Based Authentication
In order to use bearer token-based authentication, a bearer token must be obtained first. This token must then be passed along with every request in the HTTP Authorization header using the Bearer scheme.
Obtaining a Bearer Token
To obtain the token, send a request to the /my-devices/api/token endpoint, passing the following parameters as form data:
- username: The name of the user the token should be issued to.
- password: The password used to authenticate the user.
- application: The name of the application the token should be issued to.
- secret: The application secret (optional), used for reserved application names.
Example:
POST /my-devices/api/token HTTP/1.1
Host: remote.macchina.io
Content-Type: application/x-www-form-urlencoded
Content-Length: 57
username=user&password=s3cr3t&application=DemoApplication
If successful, the server will respond with a JSON containing the token in JSON Web Token (JWT) format, as well as the validity period of the token.
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 297
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEZW1vQXBwbGljYXRpb24iLCJleHAiOjE1NjczMjE1NTAuOTA4MjIyLCJpYXQiOjE1NjcyMzUxNTAuOTA4MDk2LCJqdGkiOiJkMzdjYjRlYS1lYmZkLTQyM2QtYWNjYi1kY2RjNWNkMTdiMmIiLCJzdWIiOiJ1c2VyIn0.9BWgKeW9-6kd0vqNR6GVz2XUG5bOYdPHuYlHLCGCn70",
"expires": 1567321550
}
The expiry time is given in seconds since midnight, January 1st 1970, UTC.
Passing the Bearer Token
The received bearer token must be passed in the Authorization header, using the Bearer scheme.
Example:
GET /my-devices/api/users HTTP/1.1
Host: remote.macchina.io
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEZW1vQXBwbGljYXRpb24iLCJleHAiOjE1NjczMjE1NTAuOTA4MjIyLCJpYXQiOjE1NjcyMzUxNTAuOTA4MDk2LCJqdGkiOiJkMzdjYjRlYS1lYmZkLTQyM2QtYWNjYi1kY2RjNWNkMTdiMmIiLCJzdWIiOiJ1c2VyIn0.9BWgKeW9-6kd0vqNR6GVz2XUG5bOYdPHuYlHLCGCn70
Authentication with Device Credentials
Some API requests, specifically getting and setting device properties, can also be made using device credentials. Device UUID and device password must be supplied using HTTP Basic authentication. A device password must have been set using the "password" device property. The special device UUID "self" must be used in the resource path instead of the actual device UUID (which is passed in the Authorization header).
Accessing Device Web Servers
The device web server of any device that is connected to the reflector server can be reached under the address <id>.remote.macchina.io, where <id> is the UUID identifying the device.
To access the device, a valid session cookie is required. Alternatively, HTTP Basic Authentication can be used to provide authentication info. However, as to not conflict with possible authentication required by the device itself, the authentication information is not passed via the Authorization header, but via the X-PTTH-Authorization header instead.
Example:
GET / HTTP/1.1
Host: a2359c27-cb1f-4692-8490-22d412ac87ba.remote.macchina.io
X-PTTH-Authorization: Basic dXNlcjpzM2NyM3Q=
This is a very useful feature for programmatically "pushing" data to devices, using a POST or PUT request to the device's web server.
The X-PTTH-Authorization header can also be used for bearer token-based authentication.
Example:
GET / HTTP/1.1
Host: a2359c27-cb1f-4692-8490-22d412ac87ba.remote.macchina.io
X-PTTH-Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEZW1vQXBwbGljYXRpb24iLCJleHAiOjE1NjczMjE1NTAuOTA4MjIyLCJpYXQiOjE1NjcyMzUxNTAuOTA4MDk2LCJqdGkiOiJkMzdjYjRlYS1lYmZkLTQyM2QtYWNjYi1kY2RjNWNkMTdiMmIiLCJzdWIiOiJ1c2VyIn0.9BWgKeW9-6kd0vqNR6GVz2XUG5bOYdPHuYlHLCGCn70
Browsing Devices
For browsing all available devices, send a GET request to /my-devices/api/devices. Optionally, parameters can be supplied to filter or limit the result.
To get a list of all devices, that are online, send the following request:
GET /my-devices/api/devices HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
The response will contain a JSON array of objects holding device properties (id, domain, name, online, etc.) in the body:
HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:25:31 GMT
Transfer-Encoding: chunked
[
{
"name": "Network Camera",
"geolocation": "46.528760, 14.099177",
"port": "0",
"lastConnect": "2012-03-01T11:25:02Z",
"id": "0a72da53-9de5-44c8-9adf-0090e80e20a7",
"host": "80.122.195.86",
"online": true,
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Network camera at office"
},
{
"name": "Web HMI Demo",
"geolocation": " 46.528760, 14.099177",
"port": "0",
"lastConnect": "2012-03-01T11:25:26Z",
"id": "33a9c5a3-81d8-4d3a-8068-1c910b3c61f6",
"host": "188.22.62.220",
"online": true,
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Industrial HMI built with web technologies",
"hardware": "Digi ConnectCore 9C"
},
{
"name": "iWeatherStation",
"geolocation": "46.528760, 14.099177",
"port": "0",
"lastConnect": "2012-03-01T11:25:15Z",
"id": "a2359c27-cb1f-4692-8490-22d412ac87ba",
"host": "80.122.195.86",
"online": true,
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Internet-based weather station device",
"hardware": "SSV DNP/9200"
}
]
Note: in order to improve readability, the chunk sizes have been stripped from the responses shown in this document.
The following parameters can be added:
- query: Specify a whitespace-separated list of keywords to only return devices matching these keywords. If any of the keywords are found in the name, description or tags properties of the device, then the device will be included in the result.
- sort: Specify a sort criteria to order the result by. Valid values are domain, id, host, lastConnect, name, online and protocol.
- dir: Specify sort direction. Valid values are asc (default) and desc.
- fromIndex: A zero-based index of the first desired result. This is used for paging output, along with maxResults.
- maxResults: Maximum number of results for paged output. Usually used together with fromIndex.
- status: Only include devices with the given online status. Valid values are online, offline and all.
- domain: Only include devices with the given domain. The domain UUID must be given as value.
Example: Browse for all devices containing the keyword "camera" in their name, description or tags and order by last connect time:
GET /my-devices/api/devices?query=camera&sort=lastConnect HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Server Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:19:21 GMT
Transfer-Encoding: chunked
[
{
"name": "Network Camera",
"geolocation": "46.528760, 14.099177",
"port": "0",
"lastConnect": "2012-03-01T11:19:07Z",
"id": "0a72da53-9de5-44c8-9adf-0090e80e20a7",
"host": "80.122.195.86",
"online": true,
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Network camera at office"
}
]
Example: paged results:
GET /my-devices/api/devices?firstIndex=1&maxResults=10 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Getting Properties of a Specific Device
To return all device properties for a device identified by its UUID, issue a GET request to /my-devices/api/device/<id>, where <id> is replaced with the device UUID.
Example:
GET /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Server Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:36:32 GMT
Transfer-Encoding: chunked
{
"name": "Network Camera",
"geolocation": "46.528760, 14.099177",
"port": "0",
"lastConnect": "2012-03-01T11:35:59Z",
"id": "0a72da53-9de5-44c8-9adf-0090e80e20a7",
"host": "80.122.195.86",
"online": true,
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Network camera at office"
}
It is also possible to only return a specific property. To do this, the name of the property must be added to the request URI:
GET /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7/name HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Server Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:36:32 GMT
Transfer-Encoding: chunked
{
"name": "Network Camera"
}
A device can query its own properties if a device password has been set using the "password" device property. The device UUID and password are used to authenticate the request. Instead of the device UUID, the special keyword "self" is used in the resource path.
GET /my-devices/api/device/self/name HTTP/1.1
Host: remote.macchina.io
Authorization: Basic MGE3MmRhNTMtOWRlNS00NGM4LTlhZGYtMDA5MGU4MGUyMGE3OnMzY3IzdA==
Connection: Close
Server Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:36:32 GMT
Transfer-Encoding: chunked
{
"name": "Network Camera"
}
Setting Properties of a Specific Device
The properties of a device can be modified, and new properties can be added. This is done with a PUT or PATCH request to /my-devices/api/device/<id>, where <id> is replaced with the device UUID.
The new property values are given through a JSON document in the request body.
PUT and PATCH are equivalent, although PATCH is semantically more appropriate.
Example:
PUT /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Type: application/json
Content-Length: 38
{
"name": "Network Camera"
}
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:38:24 GMT
Note: System properties (id, domain, online, lastConnect, host and port) cannot be modified with PUT or PATCH. For updating the domain property, see Creating or Updating a Device.
A device can modify its own properties if a device password has been set using the "password" device property. The device UUID and password are used to authenticate the request. Instead of the device UUID, the special keyword "self" is used in the resource path.
Example:
PUT /my-devices/api/device/self HTTP/1.1
Host: remote.macchina.io
Authorization: Basic MGE3MmRhNTMtOWRlNS00NGM4LTlhZGYtMDA5MGU4MGUyMGE3OnMzY3IzdA==
Connection: Close
Content-Type: application/json
Content-Length: 38
{
"name": "Network Camera"
}
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:38:24 GMT
Deleting a Device Property
A device property can be deleted with a DELETE request to /my-devices/api/device/<id>/<prop>, where <id> is replaced with the device UUID and <prop> is replaced with the property name.
Example:
DELETE /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7/tags HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 0
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT
Deleting a Device
A device can be deleted with a DELETE request to /my-devices/api/device/<id>, where <id> is replaced with the device UUID.
Deleting a device is normally only allowed if the device is offline (disconnected). However, by adding the X-PTTH-Force: disconnect header to the request, the device will be disconnected before being deleted.
Example:
DELETE /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 0
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT
Creating a Device
A device can be created with a POST request to /my-devices/api/device/<id>, where <id> is replaced with the device ID of the new device.
The new device properties must be passed as JSON object in the request body. The properties must at least include domain and name. The id property must not be included. The id and online properties will be set automatically. The domain UUID must be one the user account has been authorized to access.
Example:
POST /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 195
{
"name": "Network Camera",
"geolocation": "46.528760, 14.099177",
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Network camera at office"
}
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT
Creating or Updating a Device
POST can also be used to update an existing device's properties. For this to work, a X-PTTH-If-Exists: update header must be included in the request.
If this header is included, and the device with the given ID already exists, it's properties will be updated. If the device does not exist, it will be created.
This is also the only way the domain property of an existing device can be changed.
It is furthermore possible to add a X-PTTH-If-Exists: reset header to the request. In this case, if the device already exists, it will be deleted first, then immediately re-created with the new properties.
Note: Deleting a device is normally only allowed if the device is offline (disconnected). However, by adding the X-PTTH-Force: disconnect header to the request, the device will be disconnected before being deleted and subsequently recreated.
Example:
POST /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 195
X-PTTH-If-Exists: update
{
"name": "Network Camera",
"geolocation": "46.528760, 14.099177",
"domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
"description": "Network camera at office"
}
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT
HTTP Method Override (Firewall)
If your firewall does not allow HTTP PUT or HTTP DELETE requests, you can send a POST request and add the X-HTTP-Method-Override header to specify the actual method to use. Please note that method names are case sensitive.
Example:
POST /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
X-HTTP-Method-Override: DELETE
Connection: Close
Content-Length: 0
Server Response:
HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT
Cross-Origin Resource Sharing (CORS)
The API supports CORS and thus allows you to invoke the API from browser-based applications served from another domain. In the standard setup, CORS is allowed for all domains, but this can be changed by the server administrator to a specific domain, if required.
Error Handling
The following conventions are used by the API for reporting errors:
- A successful action will always result in a 200 OK response.
- If a device or property does not exist, a 404 Not Found response is returned.
- An attempt to create a device that already exists results in a 409 Conflict response.
- If no authentication information or bad credentials are provided, a 401 Unauthorized response is returned.
- An incorrect HTTP method results in a 405 Method Not Allowed response.
- If the URI is malformed, a 400 Bad Request response is returned.
- If the server encounters an error during processing the request, a 500 Internal Server Error response is returned.
cURL Examples
The well-known cURL utility can be used to test the API.
Example 1: Get a list of all devices:
curl -uuser:s3cr3t https://remote.macchina.io/my-devices/api/devices?status=all
Example 2: Get the properties of a specific device
curl -uuser:s3cr3t \
https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7
Example 3: Set a device property:
curl -uuser:s3cr3t --request PUT \
--data '{ "name": "My Network Camera" }' \
--header 'Content-Type: application/json' \
https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7
Example 4: Creating a device:
curl -uuser:s3cr3t --request POST \
--data '{ "name": "My Network Camera", "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362"}' \
--header 'Content-Type: application/json' \
https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9bc3-019dee2f20a8