Skip to main content

How To Use The impCentral API

The Electric Imp impCentral™ API provides developers with a means to access all of the functionality provided by Electric Imp’s web app, impCentral, allowing them to develop Electric Imp applications and manage devices using the tools of their choice. It also encompasses full production functionality.

Command Line Tools

If you’re looking for an existing alternative to the impCentral web app, please check out our CLI Tools to find out about development applications that make use of the impCentral API. But if you’re looking to learn how you can connect tools of your own to impCentral, read on!

Endpoint And Resource Documentation

Please see the accompanying impCentral API Reference for a full list of endpoints and resource identifiers. Please see the impCentral API Primer for descriptions of available resources.

Example Code

Examples of code which demonstrates how you can perform common tasks with the API can be found here.

impCentral API Access

URL

The impCentral API is accessed at: https://api.electricimp.com/v5

Calls to the API must be made using HTTPS not HTTP.

Access Authentication

To authorize access to the impCentral API , an initial call is made to retrieve an access token which will be used to authorize all subsequent calls to the API for a certain period of time. The access token request is authenticated using the target account’s master email address or username, and password. Access tokens are tied to the IP address of the computer used to sign in to the API.

You can retrieve an access token with the following curl call at the command line:

curl -v -X POST 'https://api.electricimp.com/v5/auth'
  -H 'Content-Type: application/json'
  -d '{"id": "jwilliams@example.com", "password": "sup3rs3cr3t"}'

This returns JSON like this:

{ "access_token":
  "5m30hNtPtFSf3NejHxMiuly+Ur5n22blLem7V+iAtx5L4ybHvaiVM1E6+Tth2lNN14+
   oxqePugjZWdft1TpLD1ySv12CjAYH1QcB7wS4Z4PKtAgvtgSSor30bL8RIz3PLadIH32dLwc=",
  "expires_in": 3600,
  "expires_at": "2016-02-19T21:05:13.993Z",
  "refresh_token": "d59a1cc008cec79454368d239b2c198618750b08b63f8c07724432bf590a9143" }

You can then use the value of access_token to authorize, for example, a request for a list of Products by providing the token in an Authorization: Bearer header:

curl -v 'https://api.electricimp.com/v5/products'
  -H 'Authorization: Bearer
    5m30hNtPtFSf3NejHxMiuly+Ur5n22blLem7V+iAtx5L4ybHvaiVM1E6+Tth2lNN14+
    oxqePugjZWdft1TpLD1ySv12CjAYH1QcB7wS4Z4PKtAgvtgSSor30bL8RIz3PLadIH32dLwc='
  -H 'Content-Type: application/vnd.api+json'

You should make a note of the access token’s expiry date and the value of the refresh_token field. After the expiry time, you will need to generate a new access token using the /auth/token endpoint to which you send the following command, including the refresh token:

curl -v -X POST 'https://api.electricimp.com/v5/auth/token'
  -H 'Content-Type: application/json'
  -d '{"token": "d59a1cc008cec79454368d239b2c198618750b08b63f8c07724432bf590a9143"}'

This returns JSON like this:

{ "access_token":
  "5m30hNtPtFSf3NejHxMiuly+Ur5n22blLem7V+iAtx5L4ybHvaiVM1E6+Tth2lNN14+
   oxqePugjZWdft1TpLD1ySv12CjAYH1QcB7wS4Z4PKtAgvtgSSor30bL8RIz3PLadIH32dLwc=",
  "expires_in": 3600,
  "expires_at": "2016-02-19T21:05:13.993Z" }

When this access token expires, re-use your original refresh token to obtain a new access token.

Login Keys

Login keys provide an alternative means of accessing an account to the usual username-password combination. A login key is used to retrieve an access tokens by providing access to the account’s resources without exposing the account credentials. For example, the owner of an account can use the API to create a login key which can then be passed to a third-party, allowing them to retrieve an initial access token without needing to provide the account holder’s username and password.

Account owners may also make use of login keys.

Login keys are not available by default, but must be created as required. Up to ten login keys can be created per account. This is done by calling the /accounts/me/login_keys endpoint. You must also provide your account password within an X-Electricimp-Password header (this is also a requirement of calls to update and delete login keys):

curl -v -X POST 'https://api.electricimp.com/v5/accounts/me/login_keys'
  -H 'Authorization: Bearer
    5m30hNtPtFSf3NejHxMiuly+Ur5n22blLem7V+iAtx5L4ybHvaiVM1E6+Tth2lNN14+
    oxqePugjZWdft1TpLD1ySv12CjAYH1QcB7wS4Z4PKtAgvtgSSor30bL8RIz3PLadIH32dLwc='
  -H 'X-Electricimp-Password: <YOUR_ACCOUNT_PASSWORD>'
  -H 'Content-Type: application/json'
  -d '{"data": { "type": "login_key" }}'

This returns JSON like this:

{ "data": { 
    "type": "login_key",
    "id": "df5f875b37f970e4",
    "attributes": { 
      "description": "",
      "usages": 2,
      "last_ip": "192.168.0.1",
      "last_user_agent": "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; 
       en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405",
      "last_used_at": "2016-02-19T21:05:13.993Z",
      "created_at": "2016-02-19T21:05:13.993Z" }
   }
}

The value of id is the login key which can then be used by a third-party to access account resources. First, they need to submit the login key to retrieve an access token:

curl -v -X POST 'https://api.electricimp.com/v5/auth/token'
  -H 'Content-Type: application/json'
  -d '{"key": "df5f875b37f970e4"}'

This returns an access token as described above which can then be used to authorize API resource requests until the access token expires. Simply call the /auth/token endpoint with the login key to gain a new access token and continue working.

Login Key Access Scope

The login key provides full access to the account with the exception of account-related functionality. A login key can be used to view a list of Products, for example, but not to generate further login keys unless the request includes the account password within a X-Electricimp-Password header.

Accounts

The impCentral API uses Account objects to represent user accounts. Much of the functionality surrounding accounts is not exposed in the API for security reasons, but some account information is exposed, to indicate which account was used to create and/or modify API objects.

References to accounts returned in data objectsrelationships objects will be an object called an Account Identifier. It comprises only id and type keys, of which the latter will always have the value "account". The value of id is the account’s UUID.

To retrieve your own account UUID, send a GET request to /accounts/me.

Retrieving Data From The API

Returned Data Structure

The impCentral API returns data as JSON. There are two primary keys: data and links. The latter is part of the API’s auto-pagination system, covered below. The value of the data key is an array of one or more data objects. What type a given object is will depend on the endpoint your call has been made to. For example, for a GET call to /products, you would receive something like:

{ "data": [
  { "type": "product",
    "id":"fc4047fc-55ae-a469-c305-2dc35db0786a",
    "attributes": {
      "name": "Hello World",
      "description": "My first Electric Imp Platform application",
      "created_at": "2017-02-14T15:42:23.929Z" },
    "relationships": {
      "owner": {
        "type": "account",
        "id": "6fc41003-548a-9d99-e4df-bc43c5e06e17" },
      "creator": {
        "type": "account",
        "id": "6fc41003-548a-9d99-e4df-bc43c5e06e17" }
      }
  } ],
  "links": {
    "first": "https://api.electricimp.com/v5/products?page%5Bnumber%5D=1",
    "self": "https://api.electricimp.com/v5/products?page%5Bnumber%5D=1" }
}

Data Pagination

Because Product, Device Group, Device and Deployment lists can be extensive, the impCentral API organizes returned data as a series of pages, each containing 20 data entries by default. Any JSON returned by the impCentral API contains a key, links, which provides an object containing a set of URLs which allow you to navigate the available pages. links uses the following keys:

  • first — The URL of the first page of data.
  • self — The URL of the current page of data.
  • next — The URL of the next page of data.

If there is only one page of data, next is omitted. If the current page is the last page, next is omitted. Page numbering starts a 1. For example:

{ "data": [...],
  "links": { 
    "first": "https://api.electricimp.com/v5/products?page%5Bnumber%5D=1",
    "self": "api.electricimp.com/v5/products?page%5Bnumber%5D=1" }
}

Each URL can be used to access the required page. For example, to retrieve the fifth page of the Products list:

curl -v 'https://api.electricimp.com/v5/products?page%5Bnumber%5D=5'
  -u 'V4.TGngRs4Ak2wYzqdTWGEwpLhOU3OLHeEWHEeq1vNOt8OxkdE0tuWuTGbTIeQ0NX8_:'

You can set the number of data points returned per page to any value between 1 and 100 (the default is 20) by adding ?page[size]=<number> to a GET call made to the endpoint.

You can request a specific page number (based on the current page size) by adding ?page[number]=<number> to a GET call made to the endpoint.

These parameters can be combined. To retrieve devices 40 through 79 from a particular Device Group, for example, you could add ?page[number]=2&page[size]=40to a device query.

Result Filtering

In addition to pagination, the data returned by calls to impCentral API endpoints can be further narrowed in scope by applying filters: optional URL-encoded parameters appended to endpoint URLs.

Object Filter By Filter Name
Product Owner ID owner.id
Device Group Owner ID,
Product ID,
Device Group Type
owner.id,
product.id,
type
Deployment Owner ID,
Creator ID,
Product ID,
Device Group ID,
SHA,
Flagged State,
Flagger ID,
Tags
owner.id,
creator.id,
product.id,
devicegroup.id,
sha,
flagged,
flagged.id,
tags
Device Owner ID,
Product ID,
Device Group ID,
Device Group Owner ID,
Device Group Type
owner.id,
product.id,
devicegroup.id,
devicegroup.owner.id,
devicegroup.type
Webhook Device Group ID devicegroup.id

IDs are the UUID values obtained from given object’s id key. All the values are strings, except flagged, which is a boolean.

Filters are applied using the standard format: ?filter[{filter_name}]=value

For example, you could use the following to obtain a list of all the Device Groups belonging to the Product of ID 5E7DC1AC-A9D8-4520-AAEB-9F9B0BC43036:

curl -v 'https://api.electricimp.com/v5/devicegroups?filter[product.id]=
  5E7DC1AC-A9D8-4520-AAEB-9F9B0BC43036'
  -u 'V4.TGngRs4Ak2wYzqdTWGEwpLhOU3OLHeEWHEeq1vNOt8OxkdE0tuWuTGbTIeQ0NX8_:'

Filters can also be combined: ?filter[{filter_name_1}]=value1&filter[{filter_name_2}]=value2

API Rate-Limiting

Request rate-limiting uses a standard token bucket algorithm. Accounts are allotted a limited number of requests per second; every request made reduces that total by one. If the total falls to zero, the next request will fail and the API will return an HTTP status code of 429. The total of available requests is increased every second, up to a maximum.

Callers should re-issue requests that resulted in a 429 after one second.

General Rate-Limits

Every response from the API includes the following headers:

  • X-RateLimit-Limit — The maximum number of concurrent requests you could make.
  • X-RateLimit-Reset — The number of milliseconds until your total is at maximum.
  • X-RateLimit-Remaining — The number of requests you could make at this moment.

Production Device Rate-Limits

In addition to the rate-limiting above, unassigning a device from a Production Device Group has additional limitations. The same logic applies, with the following additional headers:

  • X-RateLimit-Unbond-Limit — The maximum number of concurrent production unassign requests you could make.
  • X-RateLimit-Unbond-Reset — The number of milliseconds until your total is at maximum.
  • X-RateLimit-Unbond-Remaining — The number of production devices you can unassign at this moment.

Note Every device sent in an unassignment request counts against your total, whether or not that device is in the specified Device Group, or even exists.

API Errors

The impCentral API uses the following error schema. The returned JSON will contain the array errors. Each item in errors is an error object. Each error object contains the following keys:

Key Value Type Notes
code String An internal, machine-readable error code, eg. "NF001"
status String The HTTP status code generated by the error, eg. "404"
title String A human-readable error name, eg. "Resource Not Found"
detail String A human-readable error message, eg. "The resource you requested was not found"
source Object This contains the following keys:
parameter — The URL parameter passed to the API endpoint that triggered the error,
  eg. "devicegroup_id"
pointer — The request body value that caused the error

Warnings have the same format, but the response status will be 2xx and the warning will be included as a part of the meta field of the response. Errors are grouped into one of several categories, indicated by the code key:

VX — Validation errors

“You can’t do that because you gave bad inputs”

These are mostly 4xx status codes. You should almost always get a pointer or parameter property in the response body indicating what caused the error. Your request will never work if you try the same request again. Examples: VX errors are returned if you try to update an email address, submit an invalid email address, submit invalid request body.

CX — Constraint errors

“You can’t do that because of business rules”

These are mostly 4xx status codes. You may get a pointer or parameter property in the response body indicating what caused the error. Your request may work if you fix the underlying issue, eg. unassign all devices from a Device Group before deleting the group Examples: You will receive a VX error if you try to move a production device between Device Groups and the Device Groups are in different Products.

NF — Not found errors

“You can’t do that because the thing you want doesn’t exist (or you can’t see it)”

These are all 404 errors. You should usually get a pointer or parameter property in the response body indicating what caused the error. You’ll get NF errors if your input is valid but the thing you’re requesting doesn’t exist, or you don’t have permission to access it (you can’t see things in someone else’s account). Examples: You will receive an NF error if you try to fetch a device using an invalid device ID, try to fetch a Device Group in an account whose Device Groups you don’t have permission to see.

PX — Permission errors

“You can’t do that because you don’t have the right authorization”

These are 401 and 403 status codes. You’ll get these if you have invalid authorization (bad/no session token) or insufficient permission, eg. you can see a Device Group but are not permitted to modify it. Examples: You will receive a PX error if you try to list Products without a session token, or try to update a Device Group when you can only view Device Groups.

XX — Internal or other errors

“Whoops, try again later?”

These are 500, and 415, 403, 405 and 429 status codes Examples: Rate limiting, bad Content-Type headers, using HTTP rather than HTTPS, etc.

WA — Warnings

“Your request succeeded but you should know about this”

This isn’t actually an error — you’ll get back a 200 status with the warning object in the meta attribute of the response body. Examples: Requiring an unsupported library version.

Working With Devices

Restarting Devices

Individual devices can be restarted by making a POST request to the /devices/{device_ID}/restart endpoint. All of the devices in a given Device Group can be restarted by making a POST request to the /devicegroups/{devicegroup_id}/restart endpoint.

Assigning Devices to a Device Group

To assign a device to a suitable Device Group, send a POST request to the endpoint /devicegroups/{devicegroup_id}/relationships/devices and pass in a Device identifier object (or an array of Device identifiers, for multiple devices). This is a simple JSON entity which combines the device’s known ID and its object type (which is always "device"):

{ "type": "device",
  "id": "<device_id>" }

Note that the device ID is the internal device ID, retrieved from an entry in the array returned by the /devices endpoint (see below).

Unassigning Devices

A device can be removed from its Device Group by sending a DELETE request to the /devicegroups/{devicegroup_id}/relationships/devices endpoint and passing in the Device identifier (or an array of Device identifiers), as above. Devices removed this way are unassigned.

Obtaining Logs

The impCentral API provides access to two types of log message: previously posted messages (historical logs) returned in a batch, and messages returned as they are posted to the impCloud by the device (live log streaming).

Historical Logs

Historical logs for a specific device are obtained by sending a GET to the /devices/{device_id}/logs endpoint. This currently returns up to 1000 log entries for the specified device as an array in the returned data object. Each log entry is itself an object containing the following keys:

  • ts — A timestamp indicating the date and time at which the entry was logged.
  • type — The type of log entry, eg. "agent.log" or "status".
  • msg — The logged message.
  • log_type — The type of device or agent that generated the entry, eg. "development", "production" or "factory".

All available logs will be returned in reverse-chronological order (most recent first).

Note Historical log entries are not currently paginated (see ‘Data Pagination’, above). However, this may change so your code should be capable of retrieving and handling multiple pages.

Live Log Streaming

The process for receiving log entries as they are posted is as follows:

  1. Initiate a logstream.
  2. Open the logstream.
  3. Add a device to the logstream.

Live log streaming is implemented in the impCentral API using the server-sent events (SSE) protocol. Each account is allowed eight logstreams to which multiple devices may be added per stream. Further devices may be added later, and added devices removed. No more than eight devices’ logs can be streamed simultaneously. If you add a ninth device, the first device you added will automatically be removed from the logstream. If you initiate a ninth logstream, the first one will be closed immediately. Logstreams must be opened within two minutes of their creation.

Initiating a logstream involves making a POST request to the /logstream endpoint. This will return the URL of the stream. The data object in the response contains the following keys:

  • id — The log stream’s unique ID.
  • type — The type of data, ie. "logstream".
  • attributes — An object containing the following key:
    • url — The log stream URL.

A log stream URL is currently of the form /logstream/{logstream_id} but you should not assume this will always be the case, ie. you should always take the URL from the attributes.url key rather than construct it from the value of the id key.

Once you have obtained the logstream URL, you can open a connection to it: send a GET request to the URL. Until you have done so, you will not be able to add devices to the stream — attempting to do so with return an error. If the logstream is not opened within two minutes of its initiation, the ID will be revoked and you will need to initiate another logstream.

Once the logstream has been opened, you can start adding device to the logstream. You cannot add devices until the logstream is open — if it is not, the API will return an error. To add a device to the logstream, send a PUT request to the /logstream/{logstream_id}/{device_id} endpoint and provide the following JSON as the request’s body:

{ "id" : {device_id},
  "type" : "device" }

The process for manually removing a device from the stream is almost identical to that for adding devices, but instead of a PUT request make a DELETE request.

Logs are sent using the text/event-stream content type. Your code will receive each event sent by the server as text string in which one or more of the following SSE fields are embedded:

  • event — The event’s name.
  • data — The event’s data.
  • id — The event’s unique identifier.
  • retry — The reconnection time (in milliseconds) to use when attempting to re-establish the connection.

The event string is terminated with two newlines (/n/n). Fields are separated by a single newline (/n). A field’s name and its value are separated by a single colon (:) followed by one or more whitespace characters.

The impCentral API dispatches each log entry as an event, named "message" and with the log entry itself stored in the data field:

event: message
data: 0a2b3c4d5e6f7 2017-05-23T10:05:12.056Z development agent.log
      Weather forecast data received from DarkSky

By default, the log entry (the data field value) is provided as string of space-separated values:

{device_id} {timestamp} {log_type} {entry_type} {log_message}

Alternatively, the entry can provided in JSON format, in which case the above string would instead be formatted as:

event: message
data: { "deviceid" : "0a2b3c4d5e6f7", 
        "timestamp": "2017-05-23T10:05:12.056Z",
        "log_type": "development", 
        "type": "agent.log",
        "msg": "Weather forecastdata received from DarkSky" }

To specify a format, add ?format=json (or ?format=text) to the end of the logstream URL when you open the stream.

The impCentral API will also issue events named "state_change" and which provide information about the logstream itself. For example:

event: state_change
data: opened
event: state_change
data: subscribed 0a2b3c4d5e6f7
event: state_change
data: unsubscribed 0a2b3c4d5e6f7
event: state_change
data: closed

Production Functionality

The impCentral API can be used for all aspects of connected device production. The following discussion does not cover the Electric Imp Connected Factory Process, only how the API is used to configure and operate the process. For more information on the Connected Factory Process itself, please see the material in the Dev Center’s Manufacturing section, specifically the Connected Factory Overview and Connected Factory Reference.

Webhooks

The impCentral API allows you to set your optional webhooks for Device Groups via the /webhooks endpoint. You can retrieve a list of current webhooks; retrieve, update or delete specific webhooks; or create new webhooks.

Webhooks are typically applied to specific Production and Pre-production Device Groups, but they can be applied to any Device Group, though not all types of webhook are relevant to these other Device Group Types. The webhook’s target Device Group is set using its relationships.devicegroup key. The URL to which the webhook data is sent is specified by the attributes.url key, while attributes.content_type specifies how the transmitted data is formatted: "application/json" or "application/x-www-form-urlencoded".

Which event the webhook is triggered in response to is set in the object’s attributes.event key, which is a string that is "blessing", "blinkup" or "deployment". The latter is triggered whenever code is deployed to the Device Group, an event which can occur with any type of Device Group. However, "blessing" and "blinkup" are only relevant to Production and Pre-production Device Groups.

Once created and configured, webhooks will automatically fire at the specified event, until deleted or modified.

The API represents a Webhook as an object which contains the following keys:

  • id — The Webhook’s unique ID, set by the system.
  • type — The object’s type: "webhook".
  • attributes
    • url — The Webhook’s target URL, set by the user.
    • event — The Webhook’s trigger event, set by the user. This must be "blessing", "blinkup" or "deployment".
    • content_type — The format of the data sent by the webhook, set by the user. It must be "application/json" (default) or "application/x-www-form-urlencoded".
    • created_at — When the Webhook was created, set by the system.
    • updated_at — When the Webhook was last modified, set by the system.
  • relationships
    • devicegroup — The Production Device Group object the Webhook has been assigned to, set by the user.
    • creator — The Account that created the Webhook, set by the system.

For a full list of Webhook-related endpoints and actions, please see the impCentral API Specification.

Collaboration Facilities

The impCentral API does not yet fully support collaboration. It is not yet possible to issue collaboration invitations and to specify collaborators’ access permissions. However, to allow a third-party to fully access your account’s Products, Device Groups and devices, please provide them with a Login Key.

Other aspects of collaboration are supported. For example, retrieving a list of your Products will include not only your account’s Products but also other accounts’ Products to which you have been granted access. You can check a Product’s relationships.creator.id value and compare it with your own account ID to see whether it is your Product or a shared one.

Making a GET request to the accounts/<account_id> endpoint will yield extra but access-appropriate information about the sharer’s account, such as its name. Making a GET request to accounts/me will return information about your own account, including its ID.