Cloud REST API
This guide will help you to get started with using the Cloud REST API.
General
Every Managed IoT Cloud customer will get a customer specific URL to the API and an API key to use with the API. All requests
must have the x-api-key
header included in order for the API to serve the request.
Get the x-api-key
- Follow the Getting Started guide to get the manifest. Alternatively, log in to App Board and navigate to
Settings >> About
. The value shown for “Cloud Rest API” is the base of the API URL. - Using the
ApiGatewayRootUrl
from the manifest or the info from App Board, call<ApiGatewayRootUrl>/prod/metadata/manifest
. The response will contain theApiKey
.
Example for demo.mic.telenorconnexion.com
https://wrd4rfaqo1.execute-api.eu-west-1.amazonaws.com/Prod/manifest/?hostname=demo.mic.telenorconnexion.com
https://195cms8yb6.execute-api.eu-west-1.amazonaws.com/prod/metadata/manifest
API Definition
The REST API is described in the subpages of this guide, but if you as an API consumer wants to use a third party application to build an API client, you can call /metadata/swagger
that will return a Swagger 2.0 definition of the API. You can then use this swagger definition to test the API and create consumer clients. This endpoint will always reflect the current state of the API.
The API endpoint will look similar to: https://xxxxxxx.execute-api.eu-west-1.amazonaws.com/prod
.
To get a hold of data that is not specific to the Cloud REST API, you can call /metadata/manifest
to get a hold of IotEndpointATS
, UserPoolId
, UserPool
, Region
. Those parameters are needed to read from MQTT
using an authenticated user with the Thing Update API
.
Calling an unauthenticated endpoint
To call an endpoint that does not requires authentication, such as /auth/login
or /auth/register
, the only thing
required is to add the x-api-key
and run a POST
request against /auth/login
and send the payload as JSON.
Errors are communicated by sending standard HTTP Error Codes, but a generic 400
used throughout as of today.
Example request
Headers
{
"x-api-key": "The API Key to identify the request"
}
Body
{
"userName": "yourUserName",
"password": "yourPassword"
}
Unlike the legacy Cloud API, attributes are placed in the body and not within an attributes
object. The API Gateway then
wraps the attributes of the body into the attributes
object used by the legacy Cloud API. This is to simplify backwards compatibility.
Example response
Body
{
"user": {
"data": {},
"domainPath": "/",
"userName": "yourUserName",
"roleName": "ReadWrite",
"firstName": "FirstName",
"lastName": "LastName",
"email": "technicalsupport@telenorconnexion.com",
"domainName": "root"
},
"credentials": {
"identityId": "<omitted>",
"token": "<omitted>",
"refreshToken": "<omitted>"
}
}
Calling an authenticated endpoint
To call an endpoint that requires a logged in user, which includes all other endpoints except for /auth/
and /metadata
.
Since the REST API needs to be backwards compatible with the Cloud API, we need to do some setup before we can call the authenticated endpoint. As we saw in the previous example, we called /auth/login
where we got an identityId
, token
and refreshToken
wrapped in a credentials
object.
This object needs to be stored locally by the API consumer in order to remove the need to login before every request. The token
should be added to the Authorization
header that will make sure that the request is authorized.
If one of the previously mentioned data is missing from the request, the API will send a 403 forbidden
response. Please note that you always have to add x-api-key
header to your requests.
Example request
Headers
{
"Authorization": "The Authorization token returned from /auth/login",
"x-api-key": "The API Key to identify the request"
}
Request
[GET]
: https://<API_URL>/domain?attributes=id
Example response
{
"root": {
"attributes": {
"id": "root"
}
}
}
Expired tokens
Since the Id-token returned from /auth/login
only lasts for an hour you need to make sure to implement token refresh in your application.
The /auth/refresh
is used for those cases, where you enter the refreshToken
that was returned from the /auth/login
endpoint. This will give you a new token, and make it possible to extend the user session for another hour.
Error messages
If something goes wrong the response will contain an error message. The error message is split into different parts to make it possible to localize the errors. The message
field is a text representation of the error and that is the only field that is always present and it is also used for unknown errors that may occur. The messageKey
field is used to localize the message and the possible values are described with each action below.
The messageParams
field can be used to provide extra information about the error and if the error is related to a specific property it is specified in property
field. These error messages are always sent with a 400
HTTP status code.
Permissions and error messages
Error messages thrown when a user is not authorized for a resource follows a certain pattern. In general, we throw a NotFoundError
with a 404 response code. In the cases listed below we will throw a NotAuthorizedError
instead:
- If the user attempts an UPDATE or DELETE operation where the user has READ permission on the object type in the domain that the object pertains.
- If the user attempts a CREATE operation in a domain where it has a READ permission on the DOMAINS object type.
Example error
{
"message": {
"name": "LocalizableError",
"message": "Thing with externalId Demo not found",
"messageKey": "THING_NOT_FOUND"
}
}
General errors
These are the known errors that can occur that is not related to a specific action.
Key | Params | Property | Description |
---|---|---|---|
NOT_AUTHORIZED |
operation , objectType |
Returned if the user is not authorized to perform the specified action. |
Life cycle events
Some APIs also publishes life cycle events on MQTT. This can be used to listen to event concerning a specific thing or thing type and react when a new thing is created, a thing type removed or something else. The APIs that trigger life cycle events have that documented.
All events are published to the topic event/<domainPath>
(the root domain is implicit) so for a thing that belongs to the sub domain sub1
the events will be published to event/sub1
.
Example event
{
"timestamp": 1477456596272,
"message": "Thingtype with id: 1 and label: Pump created",
"classification": "INTERNAL",
"type": "THING_TYPE.CREATE",
"source": {
"thingType": 1,
"domain": "sub1"
}
}