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.
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!
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.
Examples of code which demonstrates how you can perform common tasks with the API can be found here.
The impCentral API is accessed at: https://api.electricimp.com/v5
Calls to the API must be made using HTTPS not HTTP.
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 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.
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.
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 objects’ relationships 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
.
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" }
}
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:
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]=40
to a device query.
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
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.
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.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.
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:
“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.
“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.
“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.
“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.
“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.
“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.
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.
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).
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.
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 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:
"agent.log"
or "status"
."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.
The process for receiving log entries as they are posted is as follows:
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:
"logstream"
.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:
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
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.
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:
"webhook"
."blessing"
, "blinkup"
or "deployment"
."application/json"
(default) or "application/x-www-form-urlencoded"
.For a full list of Webhook-related endpoints and actions, please see the impCentral API Specification.
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.