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

  1. 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.
  2. Using the ApiGatewayRootUrl from the manifest or the info from App Board, call <ApiGatewayRootUrl>/prod/metadata/manifest. The response will contain the ApiKey.

Example for demo.mic.telenorconnexion.com

  1. https://wrd4rfaqo1.execute-api.eu-west-1.amazonaws.com/Prod/manifest/?hostname=demo.mic.telenorconnexion.com
  2. 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"
  }
}