# iSeries IoT API
---
## Table of Contents
* [Overview](#overview)
* [The data model](#the-data-model)
* [Intended state](#intended-state)
* [API](#api)
* [Document Reader API](#document-reader-api)
* [Structure API](#structure-api)
* [Authorization](#authorization)
* [Authorization Overview](#authorization-overview)
* [OAuth 2.0 Authentication and Authorization](#oauth-20-authentication-and-authorization)
* [Permissions](#permissions)
* [REST](#rest)
* [REST Overview](#rest-overview)
* [How to Handle Redirects](#how-to-handle-redirects)
---
## Overview
### The data model
The API is represented as a JSON document with top-level attributes of metadata, devices, and structures. Your products use this JSON document to interact with, and react to, devices and related state changes.
Structures represent physical structures in the real world. They serve as an organizing point for devices and store data for the building as a whole. Typically, a structure is a user place of business.
Devices represent physical devices (Document Readers) within a structure.
> **Key Point:** All devices belong to a structure. A structure can have many devices.
Every data element in the JSON document is addressable by URL (also known as "data locations"). Products can read and write to sections of this document and subscribe to changes. This subscription capability allows products to react in real time to changes made to the system, such as turning off a reader when a gate goes out of service.
```JSON
{
"metadata": {
"access_token" :"c.FmDPkzyzaQe...",
"client_version" :1
},
"devices": {
"fingerprint_readers": { /* TODO */ },
"document_readers": {
"awJo6rH0IldT2YlIVtYaGQ": {
"device_id" :"awJo6rH...",
"software_version" :"4.0",
"structure_id" :"VqFabWH21nwVyd4RWgJgNb292wa7hG_dUwo2i2SG7j3-BOLY0BA4sw",
"where_id" :"d6reb_OZTM...",
"where_name" :"Hallway",
"name" :"Hallway (upstairs)",
"is_online" :true,
"last_is_online_change" :"2016-12-29T18:42:00.000Z",
"last_capture":{
"vis_url" :"STRING1/device_id/STRING2?auth=access_token",
"uv_url" :"STRING1/device_id/STRING2?auth=access_token",
"ir_url" :"STRING1/device_id/STRING2?auth=access_token",
},
"last_event": {
"has_document" :true,
"start_time" :"2016-12-29T00:00:00.000Z",
"end_time" :"2016-12-29T18:42:00.000Z",
}
}
}
}
"structures": {
"VqFabWH21nwVyd4RWgJgNb292wa7hG_dUwo2i2SG7j3-BOLY0BA4sw": {
"structure_id" :"VqFabWH21nwVyd4RWgJgNb292wa7hG_dUwo2i2SG7j3-BOLY0BA4sw",
"document_readers" :["peyiJNo0IldT2YlIVtYaGQ", ...],
"name" :"Terminal 2",
"wheres": {
"Fqp6wJI...": {
"where_id" :"Fqp6wJI...",
"name" :"Hall 1"
}
}
}
}
}
```
### Intended state
The service stores the authoritative state of the system, and devices subscribe to changes. Modifying this state causes the service to push a change notification to all subscribers.
B
ecause this propagation has some delay and networks can be unreliable, the state observed by a product may not be the state currently observed by other products or the service. State is eventually synchronized as messages are transmitted between various products.
> **Key Point:** The state stored in the service is the current "intended" state of the system.
This document-oriented publish/subscribe model provides responsive application interactions.
---
## API
### Document Reader API
https://`{url}`/devices/document_readers/`{device_id}`/
#### device_id
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/device_id ||
| **Returns** | `string` <br/> *example:* `'V789Typtr...'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### software_version
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/software_version ||
| **Returns** | `string` <br/> *example:* `'1.0.2'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### structure_id
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/structure_id ||
| **Returns** | `string` <br/> *example:* `'V789Typtr...'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### where_id
A unique,generated identifier that represents where_name.
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/where_id ||
| **Returns** | `string` <br/> *example:* `'V789Typtr...'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### where_name
Display name of the device' "where"
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/where_name ||
| **Returns** | `string` <br/> *example:* `'Hall 2'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### name
Display name of the device
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/name ||
| **Returns** | `string` <br/> *example:* `'Gate 7'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### is_online
Device connection status.
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/is_online ||
| **Returns** | `boolean` <br/> *example:* `true` or `false` |
| **Access** | read-only |
| **Available** | **Read:** |
#### last_is_online_change
Timestamp that identifies the last change to the online status, in ISO 8601 format.
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/last_is_online_change ||
| **Returns** | `string` <br/> *example:* `"2016-12-29T18:42:00.000Z"` |
| **Access** | read-only |
| **Available** | **Read:** |
#### last_event
`https://`{url}`/devices/document_readers/`{device_id}`/last_event`
##### has_document
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/last_event/has_document ||
| **Returns** | `string` <br/> *example:* `true` or `false` |
| **Access** | read-only |
| **Available** | **Read:** |
#### last_capture
https://`{url}`/devices/document_readers/`{device_id}`/last_capture
##### vis_url
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/last_capture/vis_url ||
| **Returns** | `string` <br/> *example:* `"STRING1/device_id/STRING2?auth=access_token"` |
| **Access** | read-only |
| **Available** | **Read:** |
##### ir_url
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/last_capture/ir_url ||
| **Returns** | `string` <br/> *example:* `"STRING1/device_id/STRING2?auth=access_token"` |
| **Access** | read-only |
| **Available** | **Read:** |
##### uv_url
| | |
| --- | --- |
| https://`{url}`/devices/document_readers/`{device_id}`/last_capture/uv_url ||
| **Returns** | `string` <br/> *example:* `"STRING1/device_id/STRING2?auth=access_token"` |
| **Access** | read-only |
| **Available** | **Read:** |
### Structure API
https://`{url}`/structures/`{structure_id}`/
#### structure_id
ID number of the structure.
| | |
| --- | --- |
| https://`{url}`/structures/`{structure_id}`/structure_id ||
| **Returns** | `string` <br/> *example:* `'V789Typtr...'` |
| **Access** | read-only |
| **Available** | **Read:** |
#### document_readers
List of document_readers in the structure, byt device identifier.
| | |
| --- | --- |
| https://`{url}`/structures/`{structure_id}`/document_readers ||
| **Returns** | `string[]` <br/> *example:* `['V789Typtr...',... ]` |
| **Access** | read-only |
| **Available** | **Read:** |
#### name
User defined name of the structure.
| | |
| --- | --- |
| https://`{url}`/structures/`{structure_id}`/name ||
| **Returns** | `string` <br/> *example:* `'Terminal 1'` |
| **Access** | read/write |
| **Available** | **Read:** <br/> **Write:** |
#### wheres
User defined name of the structure.
| | |
| --- | --- |
| https://`{url}`/structures/`{structure_id}`/wheres ||
| **Returns** | `object[]` <br/> *example:* `'Terminal 1'` |
| **Access** | read-only |
| **Available** | **Read:** <br/> **Write:** |
---
## Authorization
### Authorization Overview
The API provides information that you can use to capture customer information for a user. The information is ultimately owned by users, and users can explicitly choose to share this information with your product.
The purpose of authorization is to give your customers a secure means to grant access to their device data.
#### Product site or app before authorization
In your product site or app, you can provide a way for customers to give your product access to their device data. To do this, create a button or other UI element to initiate the OAuth flow.
When you build user authorization into your app, you can either:
- use an external browser to authorize an app
- use a new page to auth a webapp
> **Warning:** Do not use iFrames for user authorization.
#### Login
The user is prompted to login.
#### Permissions
We'll prompt the user to grant access to your product. This page displays the permissions and descriptions you entered when you created your client.
#### Product site or app after authorization
After your customer authorizes your product, we'll send an authorization code that your product can exchange for an access token. Your product can then send the access token with API calls to access Nest data.
Your customers can revoke access at any time, which will prevent your product from making further requests for the customer's device data.
### OAuth 2.0 Authentication and Authorization
```mermaid
sequenceDiagram
autonumber
actor U as User
participant P as Your Product
participant C as Cloud
P->>C: Request Authorization
activate C
activate P
U->>C: User Login & Consent
C-->>P: Authorization Code
deactivate C
deactivate P
P->>C: Exchange code for token
activate P
activate C
C-->>P: Token response
deactivate P
deactivate C
P->>C: Use Token to call API
```
---
## Permissions
### Document Reader
| document_reader | |
| --- | --- |
| document_reader read | Grants read permission to all values |
| document_reader read/write | Grants read permission to all values <br/> Grants write permission to <ul><li>`name`</li><li>`enabled`</li></ul>|
### Structure
| structure | |
| --- | --- |
| structure read | Grants read permission to all values |
| structure read/write | Grants read permission to all values <br/> Grants write permission to `name` |
---
## REST
### REST Overview
REST is a lightweight, stateless web service standard that you can use within your products for ad-hoc one-off calls, proof-of-concept labs, troubleshooting, apps that poll approximately every minute, and refresh button implementations.
The REST interface uses the iSeries IoT API Data Model URL as an endpoint.
### How to Handle Redirects
Some programming languages have HTTP implementations that require special handling for redirects.
In response to a REST API request, the Nest API server returns a redirect. The REST client detects the redirect and requests the page that the client was redirected to. Some HTTP implementations do not forward the Authorization header to the redirected URI, and this results in a 401 Unauthorized error.
For example, suppose you ask for foo.com. The foo.com server responds with a redirect to bar.com. Postman or Curl pass the Authorization header to foo and then to bar. Other HTTP implementations, such as Golang's and Python's, do not automatically pass the Authorization header to the redirected URI.
#### How it works
The following sequence diagram shows what happens when a redirect occurs.
```mermaid
sequenceDiagram
participant API Client
participant Developer API
participant Data Store
Note left of API Client: First HTTP<br/>Request!
API Client->>Developer API: GET from API url
Developer API-->>API Client: 307 Redirect to Data Store URL
Note left of API Client: Second HTTP<br/>Request!
API Client->>Data Store: GET from Data Store URL
Data Store-->>API Client: 200 w/ JSON Payload in HTTP Body
```