The Particle Device Cloud API is a REST API. REST means a lot of things, but first and foremost it means that we use the URL in the way that it's intended: as a "Uniform Resource Locator".
In this case, the unique "resource" in question is your device (Argon, Boron, Photon 2).
Every device has a URL, which can be used to GET
variables, POST
a function call, or PUT
new firmware.
The variables and functions that you have written in your firmware are exposed as subresources under the device.
All requests to the API server require TLSv1.2 or later.
PROTOCOL AND HOST
"https://api.particle.io"
Formatting note: When we write something prefixed with a colon :
, we mean you should substitute your own information.
For example when you see something like /v1/devices/:deviceId
you might code something like /v1/devices/55ff8800beefcafe12345678
.
For product endpoints, you need to specify which product the API call targets. You can use either the product ID or the short alphanumerical product slug. Get either from the Console. In this example, the product ID is 1337 and the product slug is my-product-v1
.
The Particle API accepts requests in JSON (content type application/json
) and in form encoded format (content type application/x-www-form-urlencoded
). It always replies with JSON (content type application/json
).
# Example with form encoded format
curl https://api.particle.io/v1/devices/mydevice/wakeup \
-d arg=please \
-H "Authorization: Bearer :access_token"
# Same example with JSON
curl https://api.particle.io/v1/devices/mydevice/wakeup \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d "{\"arg\": \"please\"}"
In these docs, you'll see example calls written using a terminal program called curl which may already be available on your machine.
The examples use form encoded data to make them easier to read and type but unless specified otherwise any endpoint can also accept a JSON object with the parameters as properties.
In addition to using curl, you can use Postman a 3rd-party product that provides a web-based graphical interface for making API calls.
To making using Postman significantly easier, download these two files:
Use the Import feature to import these two files into Postman. The Particle API file will be updated periodically as new APIs are added, but the environment file is intended to be imported only once and then updated with your settings, like your Particle account username.
Once you've imported the Particle Postman Environment you can select it from the popup in the upper right corner of the Postman workspace window.
Using a quickly expiring access token is a good way to maintain security when using Postman. You can easily do this using the Particle CLI.
The parameter is the number of seconds, so 3600 is one hour. If you leave off the --expires-in
option, the token will be good for 90 days. You can also create a non-expiring token.
particle token create --expires-in 3600
To use this token, select Particle API Environment in the upper right corner of the Postman workspace (1).
Click the eye icon next to it to view the configuration (2).
Paste in the access token in the access_token
field (3).
It's also possible to enter your username and password in the Postman environment, and also possible to generate the token from within Postman itself. However, these techniques are hard to use if you have multi-factor authentication (MFA) enabled on your Particle account. The CLI and access_token
technique above works both with and without MFA enabled.
A good way to test out your access token is use List devices.
Open Collections then Particle API then Devices then List devices.
If you've entered the access_token in the previous step, there should be a small green circle on the Authorization tab.
Click the blue Send button.
You should get output with information about your devices in the bottom pane.
Open Collections then Particle API then Devices then Call a function.
In the Params tab, enter the device ID you want to call in deviceid and the function name in functionName. In this case, we're using the Blink and LED firmware on the device, so it will respond to the led function.
Just because you've connected your Particle device to the internet doesn't mean anyone else should have access to it. Permissions for controlling and communicating with your Particle device are managed with OAuth2.
# You type in your terminal
curl https://api.particle.io/v1/devices/0123456789abcdef01234567/brew \
-H "Authorization: Bearer 9876987698769876987698769876987698769876"
# Response status is 200 OK, which means
# the device says, "Yes ma'am!"
# Sneaky Pete tries the same thing in his terminal
curl https://api.particle.io/v1/devices/0123456789abcdef01234567/brew \
-H "Authorization: Bearer 1234123412341234123412341234123412341234"
# Response status is 403 Forbidden, which means
# the device says, "You ain't the boss of me."
# LESSON: Protect your access token.
You can create an access token using the Particle CLI.
When you connect your Particle device to the Cloud for the first time, it will be associated with your account, and only you will have permission to control your Particle device—using your access token.
There are three ways to send your access token in a request.
To send a custom header using curl, use you the -H
flag.
The access token is called a "Bearer" token and goes in the standard
HTTP Authorization
header.
curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" \
https://...
Sending the access token in the query string is deprecated and discouraged for new application
since many tools log query strings so there's a chance for your access token to be logged in places
where you don't expect it. Legacy applications sending access_token=38bb...
in the query string
should be updated to use the HTTP Authorization header. When using a query string in the terminal,
enclose the entire URL in double quotes to avoid issues with special characters.
curl "https://api.particle.io/v1/devices?access_token=38bb7b318cc6898c80317decb34525844bc9db55"
Sending the access token as part of the request body is deprecated since it only works for POST and PUT requests. Prefer using the HTTP Authorization header since it works for all request types.
curl -d access_token=38bb7b318cc6898c80317decb34525844bc9db55 \
https://...
POST /oauth/token
Creates an access token that gives you access to the Cloud API.
You must give a valid OAuth client ID and secret in HTTP Basic Auth or in the client_id
and client_secret
parameters. For controlling your own developer account, you can use particle:particle
. Otherwise use a valid OAuth
Client ID and Secret. This endpoint doesn't accept JSON requests, only form encoded requests. See
OAuth Clients.
Refresh tokens only work for product tokens, and even then they are not particularly useful. In order to generate a new access token from the refresh token you still need the client ID and secret. Because of this, it's simpler to just generate a new token, and then you don't need to remember and keep secure the refresh token. Also refresh tokens have a lifetime of 14 days, much shorter than the default access token lifetime of 90 days.
Must be set to application/x-www-form-urlencoded
HTTP Basic Auth where username is the OAuth client ID and password is the OAuth client secret. Any client ID will work, but we suggest particle:particle
.
OAuth client ID. Required if no Authorization header is present.
OAuth client secret. Required if no Authorization header is present.
OAuth grant type. Usually password
.
Your Particle account username
Your Particle account password
How many seconds the token will be valid for. 0
means forever. Short lived tokens are better for security.
When should the token expire? This should be an ISO8601 formatted date string.
$ curl https://api.particle.io/oauth/token \
-u particle:particle \
-d grant_type=password \
-d "username=joe@example.com" \
-d "password=SuperSecret"
The magical token you will use for all the other requests
Always set to "Bearer"
The number of seconds this token is valid for. Defaults to 7776000 seconds (90 days) if unspecified in the request. 0
means forever.
Used to generate a new access token when it has expired.
POST /oauth/token
HTTP/1.1 200 OK
{
"access_token": "254406f79c1999af65a7df4388971354f85cfee9",
"token_type": "bearer",
"expires_in": 7776000,
"refresh_token": "b5b901e8760164e134199bc2c3dd1d228acf2d90"
}
The machine readable code identifying the error
The human readable reason for the error
The two-factor authentication state code that must be sent back with the one-time password
POST /oauth/token
HTTP/1.1 400 Bad Request
{
"error": "invalid_grant",
"error_description": "User credentials are invalid"
}
POST /oauth/token
HTTP/1.1 403 Forbidden
{
"error": "mfa_required",
"error_description": "Multifactor authentication required",
"mfa_token": "eyJ0eXAiOiJKV1QiLCJhbGci....D3QCiQ"
}
GET /v1/access_tokens
Retrieve a list of all the issued access tokens for your account
Note: Pass your Particle username and password using HTTP Basic Auth.
Your Particle username and password
Token given from your MFA device. Usually 6 digits long
$ curl https://api.particle.io/v1/access_tokens \
-u "joe@example.com:SuperSecret"
List of access tokens
Access token
Date the token expires and is no longer valid
Client program used to create the token
GET /v1/access_tokens
HTTP/1.1 200 OK
[
{
"token": "b5b901e8760164e134199bc2c3dd1d228acf2d98",
"expires_at": "2014-04-27T02:20:36.177Z",
"client": "particle"
},
{
"token": "ba54b6bb71a43b7612bdc7c972914604a078892b",
"expires_at": "2014-04-27T06:31:08.991Z",
"client": "particle"
}
]
DELETE /v1/access_tokens/:token
Delete your unused or lost tokens.
DEPRECATED. Use the DELETE /v1/access_tokens/current
endpoint instead.
Access Token to delete
$ curl -X DELETE https://api.particle.io/v1/access_tokens/123abc \
-u "joe@example.com:SuperSecret"
Whether the token was deleted
DELETE /v1/access_tokens/123abc
HTTP/1.1 200 OK
{
"ok": true
}
DELETE /v1/access_tokens
Delete all your active access tokens.
$ curl -X DELETE https://api.particle.io/v1/access_tokens -H "Authorization: Bearer :access_token"
Whether the tokens were deleted
DELETE /v1/access_tokens
HTTP/1.1 200 OK
{
"ok": true
}
DELETE /v1/access_tokens/current
Delete your currently used token.
$ curl -X DELETE https://api.particle.io/v1/access_tokens/current \
-H "Authorization: Bearer :access_token"
Whether the token was deleted
DELETE /v1/access_tokens/current
HTTP/1.1 200 OK
{
"ok": true
}
GET /v1/access_tokens/current
Get your currently used token.
$ curl https://api.particle.io/v1/access_tokens/current -H "Authorization: Bearer :access_token"
The number of seconds this token is valid for. 0
means forever.
Client program used to create the token.
List of scopes for this token.
List of orgs this token has access to.
GET /v1/access_tokens/current
HTTP/1.1 200 OK
{
"expires_at": "2014-04-27T06:31:08.991Z",
"client": "particle",
"scopes": [],
"orgs": []
}
An OAuth client generally represents an app. The Particle CLI is a client, as are the Particle Web IDE, the Particle iOS app, and the Particle Android app. You too can create your own clients. You should create separate clients for each of your web and mobile apps that hit the Particle API.
Some requests, like generating an access token, require you to specify an OAuth
client ID and secret using HTTP Basic authentication. Normally, when calling the
Particle API as a single developer user to access your own account, you can use
particle
for both the client ID and secret as in the example above for
generating an access token.
curl -u particle:particle https://...
However, especially when you are creating a product on the Particle platform and your web app needs to hit our API on behalf of your customers, you need to create your own client.
NEVER expose the client secret to a browser. If, for example, you have a client that controls all your organization's products, and you use the client secret in front-end JavaScript, then a tech-savvy customer using your website can read the secret in her developer console and hack all your customers' devices.
GET /v1/clients
Get a list of all existing OAuth clients, either owned by the authenticated user or clients associated with a product.
clients:list
Product ID or slug. Product endpoint only.
$ curl https://api.particle.io/v1/clients \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/clients \
-H "Authorization: Bearer :access_token"
An array of OAuth clients
Only for clients with type: "web"
GET /v1/clients
HTTP/1.1 200 OK
{
"ok":true,
"clients": [
{
"name":"server",
"type":"installed",
"id":"server-999"
},
{
"name":"Mobile App",
"type":"installed",
"id":"mobile-app-1234"
}
]
}
POST /v1/clients
Create an OAuth client that represents an app.
Use type=installed
for most web and mobile apps. If you want to have Particle users login to their account on Particle in order to give your app access to their devices, then you can go through the full OAuth authorization code grant flow using type=web
.
This is the same way you authorize it is similar to the way you give any app access to your Facebook or Twitter account.
Your client secret will never be displayed again! Save it in a safe place.
If you use type=web
then you will also need to pass a redirect_uri
parameter in the POST body. This is the URL where users will be redirected after telling Particle they are willing to give your app access to their devices.
The scopes provided only contain the object
and action
parts, skipping the domain
which is being infered from the context.
If you are building a web or mobile application for your Particle product, you should use the product-specific endpoint for creating a client (POST /v1/products/:productIdOrSlug/clients
). This will grant this client (and access tokens generated
by this client) access to product-specific behaviors like
calling functions and
checking variables on product devices,
creating customers, and
generating customer scoped access tokens.
clients:create
Product ID or slug. Product endpoint only.
The name of the OAuth client
web
or installed
. web
is used for the authorization code grant flow similar to Facebook, and Twitter use.
Only required for web
type. URL that you wish us to redirect to after the OAuth flow.
Limits the scope of what the access tokens created using the client are allowed to do. Provide a space separated list of scopes. The only current valid scopes are customers:create
and *:*
for full control.
$ curl https://api.particle.io/v1/clients \
-d name=MyApp \
-d type=installed \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/clients \
-d name=MyApp \
-d type=installed \
-H "Authorization: Bearer :access_token"
Save this! It will never be shown again.
Only for clients with type: "web"
POST /v1/clients
HTTP/1.1 200 OK
{
"ok": true,
"client": {
"name": "MyApp",
"type": "installed",
"id": "myapp-2146",
"secret": "615c620d647b6e1dab13bef1695c120b0293c342"
}
}
PUT /v1/clients/:clientId
Update the name
or scope
of an existing OAuth client.
clients:update
The client ID to update
Product ID or slug. Product endpoint only.
Give the OAuth client a new name
Update the scope of the OAuth client. to only allow customer creation from the client or pass none
to remove all scopes (full permissions)
$ curl -X PUT https://api.particle.io/v1/clients/client-123 \
-d name="My App 2" \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/clients/client-123 \
-d name="My App 2" \
-H "Authorization: Bearer :access_token"
The updated client
PUT /v1/clients/client-123
HTTP/1.1 200 OK
{
"ok": true,
"client": {
"name": "My App 2",
"type": "installed",
"id": "myapp-2146",
"secret": "615c620d647b6e1dab13bef1695c120b0293c342"
}
}
DELETE /v1/clients/:clientId
Remove an OAuth client
clients:remove
The client ID to delete
Product ID or slug. Product endpoint only.
$ curl -X DELETE https://api.particle.io/v1/clients/client-123 \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE https://api.particle.io/v1/products/:productIdOrSlug/clients/client-123 \
-H "Authorization: Bearer :access_token"
DELETE /v1/clients/:clientId
HTTP/1.1 204 No Content
The Particle Device Cloud uses traditional HTTP response codes to provide feedback from the device regarding the validity of the request and its success or failure. As with other HTTP resources, response codes in the 200 range indicate success; codes in the 400 range indicate failure due to the information provided; codes in the 500 range indicate failure within Particle's server infrastructure.
200 OK - API call successfully delivered to the device and executed.
400 Bad Request - Your request is not understood by the device, or the requested subresource (variable/function) has not been exposed.
401 Unauthorized - Your access token is not valid.
403 Forbidden - Your access token is not authorized to interface with this device.
404 Not Found - The device you requested is not currently connected to the cloud.
408 Timed Out - The cloud experienced a significant delay when trying to reach the device.
429 Too Many Requests - You are either making requests too often or too many at the same time. Please slow down.
500 Server errors - Fail whale. Something's wrong on our end.
An API user account is a specific type of user account in the Particle platform that is designed to replace using 'human' accounts for programmatic tasks. It allows the creation of tightly scoped users that are unable to do things that machines shouldn't need to do - like log into the console, or administer accounts. This allows you to better enforce the security principle of least privilege.
Currently, API users are created, updated and deleted via the REST API, and are visible in the console, in either the product team or organization view. API users cannot log into the console, administer users, receive emails - or generally do other things that are reserved for humans.
The API User Tutorial has interactive controls in the web page that allow you to easily create, list, and delete API users for products and organizations. These controls allow you to both easily perform these operations on your account, and also learn how the APIs work, without needing to use curl or Postman.
Use an access token with permission to create users in your organization or product (administrator account). Pass a request to the relevant endpoint with a friendly name, and the desired scope(s) for the user.
curl https://api.particle.io/v1/orgs/:orgIDorSlug/team \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{
"friendly_name": "org api user",
"scopes": [ "devices:list" ]
}'
The resulting access token can then be used by programmatic processes. As always, access tokens are sensitive and should be treated as secrets.
curl https://api.particle.io/v1/products/:productIDorSlug/team \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{
"friendly_name": "product api user",
"scopes": [ "devices:list" ]
}'
The API will return an access token based on that user, for example:
{"ok":true,"created":{"username":"example-api-user+g7lvvcczos@api.particle.io","is_programmatic":true,"tokens":[{"token":"yyyyyyyyy"}]}}
"scopes": [ "devices:list","sims:list" ]
Multiple scopes can be assigned to an API user as follows:
The Particle API documentation includes the required scopes needed to call a particular API function. To determine which scope(s) to assign your API user, determine the minimum set of API functions they should be able to call.
curl -X PUT https://api.particle.io/v1/products/12857/team/example-api-user+6fbl2q577b@api.particle.io \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{
"friendly_name": "Updated API user",
"scopes": [ "devices:list", "sims:list", "customers:list" ]
}'
To modify the permissions associated with an API user, you must update the scopes via the REST API. Remember, when scopes assigned to a user change, the access token is updated and a fresh token is returned, to avoid scope creep. Depending on the scenario, it may be optimal to create a fresh user with updated permissions first, update the access token in use by the script/code/function, and then delete the old user. To update the API user, you pass in the full username, in this case example-api-user+6fbl2q577b@api.particle.io.
curl -X GET https://api.particle.io/v1/products/12857/team/ \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json"
Listing API users is done by getting the team member list of the product or for the organization. Both regular and API users are returned, however you can tell API users as they have the is_programmatic
flag set to true in the user array element:
{
"ok": true,
"team": [
{
"username": "user@example.com",
"role": {
"id": "000000000000000000000002",
"name": "Administrator"
}
},
{
"username": "example-api-user+6fbl2q577b@api.particle.io",
"is_programmatic": true
}
]
}
curl -X DELETE https://api.particle.io/v1/products/12857/team/example-api-user+6fbl2q577b@api.particle.io \
-H "Authorization: Bearer :access_token"
To delete an API user and its associated access token, simply:
{"error":"unauthorized","error_description":"API users are not allowed to call this endpoint"}
If an API user attempts to perform an action that it is not permitted to, a standard 400 unauthorized error is returned. In the event that an API user tries to hit an endpoint that no API user is authorized to access, then this error is returned:
The following API rate limits apply. Exceeding the rate limit will result in a 429 HTTP error response.
One situation that can cause problems is continuously monitoring variables for change. If you're polling every few seconds it's not a problem for a single device and variable. But if you are trying to monitor many devices, or have a classroom of students each polling their own device, you can easily exceed the API rate limit.
Having the device call Particle.publish when the value changes may be more efficient.
If you get a 401 (Unauthorized), your access token has probably expired so retransmitting the request won't help.
If you get a 429 (Too many requests) you've already hit the limit, so making another request immediately will not help.
In response to most error conditions you may want to consider a delay before retrying the request.
The API endpoints all start with /v1
to represent the first official
version of the Particle Device Cloud API.
The existing API is stable, and we may add new endpoints with the /v1
prefix.
If in the future we make backwards-incompatible changes to the API, the new endpoints will start with
something different, probably /v2
. If we decide to deprecate any /v1
endpoints,
we'll give you lots of notice and a clear upgrade path.
Note: Cellular devices may indicate that the device is online for up to 46 minutes after the device has gone offline because it went out of range or was powered off. Wi-Fi devices will generally be accurate to within a few minutes. Online indications are should occur immediately if the device was previously offline for both cellular and Wi-Fi.
GET /v1/devices
List devices the currently authenticated user has access to. By default, devices will be sorted by last_handshake_at
in descending order.
$ curl https://api.particle.io/v1/devices \
-H "Authorization: Bearer :access_token"
Array of devices. See Get device information for the response attributes of each device.
GET /v1/devices
HTTP/1.1 200 OK
[
{
"id": "53ff6f0650723",
"name": "plumber_laser",
"last_ip_address": "10.0.0.1",
"last_heard": "2020-05-28T14:46:07.586Z",
"last_handshake_at": "2020-05-27T18:13:01.059Z",
"product_id": 6,
"online": true,
"platform_id": 6,
"cellular": false,
"notes": "laser!",
"functions": [
"fire"
],
"variables": {
"power": "int32"
},
"status": "normal",
"serial_number": "PH1234",
"mac_wifi": "00:00:00:AA:BB:00",
"system_firmware_version": "1.5.0"
},
{
"id": "53ff291839887",
"name": "particle_love",
"last_ip_address": "10.0.0.1",
"last_heard": "2020-05-28T14:46:07.586Z",
"last_handshake_at": "2020-05-27T18:13:01.059Z",
"product_id": 10,
"online": false,
"platform_id": 10,
"notes": null,
"functions": [],
"variables": {},
"cellular": true,
"status": "normal",
"serial_number": "E261234",
"iccid": "1111111111111111111",
"imei": "333333333333333",
"system_firmware_version": "1.5.0"
}
]
GET /v1/products/:productIdOrSlug/devices
List all devices that are part of a product. Results are paginated, by default returns 25 device records per page.
devices:list
Product ID or Slug
Filter results to devices with this ID (partial matching)
Comma separated list of full group names to filter results to devices belonging to these groups only
Filter results to devices with this name (partial matching)
Filter results to devices with this serial number (partial matching)
The attribute by which to sort results. Options for sorting are deviceName
, deviceId
, firmwareVersion
, or lastConnection
. By default, if no sortAttr
parameter is set, devices will
be sorted by last connection, in descending order
The direction of sorting. Pass asc
for ascending sorting or desc
for descending sorting
include / exclude quarantined devices
Current page of results
Records per page
$ curl https://api.particle.io/v1/products/:productIdOrSlug/devices \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/products/:productIdOrSlug/devices?groups=beta" \
-H "Authorization: Bearer :access_token"
An array of devices objects. See Get device information for the response attributes of each device.
An array of customer objects
Customer ID
Customer username
Pagination metadata
Total number of pages of device records
GET /v1/products/:productIdOrSlug/devices
HTTP/1.1 200 OK
{
"devices": [
{
"id":"1d002a000547343232363230",
"name":"jeff_test_device",
"last_ip_address":"199.230.10.194",
"last_heard":"2016-06-10T15:00:07.100Z",
"last_handshake_at":"2016-06-10T14:56:27.100Z",
"product_id":295,
"online":false,
"platform_id": 13,
"cellular": true,
"functions": [
"cmd"
],
"variables": {
"temperature": "double"
},
"status": "normal",
"serial_number": "E40KAB111111111",
"iccid": "89014111111111111111",
"imei": "352753090000000",
"mac_wifi": "00:00:00:AA:BB:00",
"mobile_secret": "WBPYG6CPLRCFK4S",
"system_firmware_version": "3.0.0",
"firmware_product_id": 295,
"groups":["asia","europe"],
"firmware_version":3,
"desired_firmware_version": null,
"targeted_firmware_release_version": 3,
"development":false,
"quarantined":false,
"denied":false,
"owner":"jeff@particle.io"
},
{
"id":"32001e000747343337373738",
"last_ip_address":"199.21.86.18",
"last_heard":"2016-06-10T15:00:07.100Z",
"last_handshake_at":"2016-06-10T14:56:27.100Z",
"product_id":13,
"online":false,
"platform_id": 13,
"cellular": true,
"status": "normal",
"serial_number": "E40KAB111111112",
"iccid": "89014111111111111112",
"imei": "352753090000001",
"mac_wifi": "00:00:00:AA:BB:01",
"mobile_secret": "VNH9JNXMXW5YY9X",
"system_firmware_version": "2.0.0",
"firmware_product_id": 295,
"development": false,
"quarantined": true,
"denied": false
},
...
],
"customers": [
{
id:"123abc3456",
username: "customer@gmail.com",
}
],
"meta": {
"total_pages":1
}
}
POST /v1/products/:productIdOrSlug/devices
Import devices into a product. Devices must be of the same platform type as the product in order to be successfully imported. Imported devices may receive an immediate OTA firmware update to the product's released firmware.
Importing a device with a Particle SIM card will also import the SIM card into the product and activate the SIM card.
devices:import
Product ID or Slug
A device ID to import into a product. Pass id
if you are trying to import a single device
An array of device ID to import into a product. Pass ids
if you are trying to import multiple device
Import SIM card associated with each device into the product
The username (email) of a Particle user to claim the imported devices. This user must be a member of the product team.
A .txt file containing a single-column list of device identifiers: device IDs, serial numbers, IMEIs or ICCIDs. This is an alternative to ids
for importing many devices into a product at once. Encoded in multipart/form-data
format
$ curl "https://api.particle.io/v1/products/:productIdOrSlug/devices?claim_user=user@domain.com" \
-H "Authorization: Bearer :access_token" \
-F file=@devices.txt
$ curl https://api.particle.io/v1/products/:productIdOrSlug/devices
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{ "ids":["abc123"], "claim_user": "user@domain.com" }'
The number of devices successfully added to the product
Device identifiers that have been added to the product. The identifiers correspond to what was passed in the file
or id
field of the request, so they could be device IDs, serial numbers, IMEIs or ICCIDs.
Device identifiers that were already in the product
Device identifiers that belong to another owner and could not be imported
Device identifiers that were invalid and could not be imported
Device identifiers that are protected and could not be imported into a non-protected product
POST /v1/products/:productIdOrSlug/devices
HTTP/1.1 200 OK
{
"updated":1,
"updatedDeviceIds":["abc1234"],
"existingDeviceIds":[],
"nonmemberDeviceIds":[],
"invalidDeviceIds":[],
"protectedDeviceIds": []
}
GET /v1/devices/:deviceId
Get basic information about the given device, including the custom variables and functions it has exposed. This can be called for sandbox devices claimed to your account and for product devices you have access to, regardless of claiming.
Device ID
$ curl https://api.particle.io/v1/devices/0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/devices/0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token"
Device ID
Device name
Particle username for the user who claimed this device
IP address of the device the last time it connected to the cloud
Date and Time that the cloud last heard from the device in ISO 8601 format
Date and time that the device most recently connected to the cloud in ISO 8601 format
For development devices, this equals platform_id. For product devices, your product number.
Indicates whether the device is currently connected to the cloud
Deprecated. Use online
Indicates the type of device. Example values are 6
for Photon, 10
for Electron, 12
for Argon, 13
for Boron.
True for cellular devices (Electron, Boron), false otherwise
Free-form notes about the device
List of function names exposed by the device
List of variable name and types exposed by the device
The serial number of the device, if it exists
When normal
indicates the is running user application, when safe_mode
indicates that the device has missing Device OS dependencies and is not running the user application.
Last SIM card ID used for cellular devices
Deprecated. Use iccid
.
IMEI number for cellular devices
The device MAC address if it has one. Non cellular devices only
Version of Device OS running on the device last reported to the cloud
Deprecated. Use system_firmware_version
.
Version of Device OS to use when compiling firmware for this device in the Web IDE. If not set, uses default_build_target
.
Version of Device OS to use when compiling firmware for the platform of this device in the Web IDE.
Indicates whether the device will accept firmware updates without being forced
Indicates whether firmware updates on the device have been forced from the cloud.
The shared secret used by a mobile app to communicate securely with a device over BLE during setup
The product ID that the device reported in its firmware the last time it connected to the cloud. Product devices only
An array of group names that the device belongs to. Product devices only
The version number the device reported in its firmware. Product devices only
The version of firmware that the device has been individually locked to run. Product devices only
The product firmware version the device is targeted to receive based on the locked version and released firmware. If firmware_version
matches targeted_firmware_release_version
, the device is currently running this firmware. Product endpoint only
Set to true
if a device has been marked as a development device, meaning it will not receive any product firmware updates from the cloud. Product endpoint only
If set to true
, the device is unrecognized and has lost product privileges until it is manually approved. Product endpoint only
If set to true
, this is a quarantined device that has been permanently denied access to product privileges. Product endpoint only
The device protection status of this device
GET /v1/devices/0123456789abcdef01234567
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"name": "gongbot",
"owner": "someone@particle.io",
"last_ip_address": "176.83.211.237",
"last_heard": "2015-07-17T22:28:40.907Z",
"last_handshake_at": "2015-07-15T20:08:00.456Z",
"product_id": 13,
"online": true,
"platform_id": 13,
"cellular": true,
"notes": null,
"functions": [
"gong",
"goto"
],
"variables": {
"Gongs": "int32"
},
"status": "normal",
"serial_number": "AAAAAA111111111",
"iccid": "89314404000111111111",
"imei": "357520000000000",
"mac_wifi": "00:00:00:AA:BB:00",
"mobile_secret": "NVYM5RK6AHCBELA",
"system_firmware_version": "1.5.0",
"firmware_updates_enabled": true,
"firmware_updates_forced": false,
"device_protection": {
"status": "disabled"
}
}
GET /v1/products/:productIdOrSlug/devices/:deviceId
Get basic information about a given device that is part of a product
See Get device information for the response attributes
devices:get
Device ID
Product ID or Slug
GET /v1/devices/:deviceId/:varName
Request the current value of a variable exposed by the device. Variables can be read on a device you own, or for any device that is part of a product you are a team member of.
devices.variable:get
Device ID
Variable name
Product ID or Slug. Product endpoint only.
Specify raw
if you just the value returned
$ curl https://api.particle.io/v1/devices/0123456789abcdef01234567/temperature \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/devices/0123456789abcdef01234567/temperature \
-H "Authorization: Bearer :access_token"
The variable value
The variable name
The device information
GET /v1/devices/0123456789abcdef01234567/temperature
HTTP/1.1 200 OK
{
"name": "temperature",
"result": 46,
"coreInfo": {
"name": "weatherman",
"deviceID": "0123456789abcdef01234567",
"connected": true,
"last_handshake_at": "2015-07-17T22:28:40.907Z",
}
}
GET /v1/devices/0123456789abcdef01234567/temperature?format=raw
HTTP/1.1 200 OK
46
POST /v1/devices/:deviceId/:functionName
Call a function exposed by the device, with arguments passed in the request body. Functions can be called on a device you own, or for any device that is part of a product you are a team member of.
devices.function:call
Product ID or Slug. Product endpoint only.
Function argument with a maximum length of 63 characters
Specify if you just want the function return value returned
$ curl https://api.particle.io/v1/devices/0123456789abcdef01234567/gong \
-d arg="ZEN PLEASE" \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/devices/0123456789abcdef01234567/gong \
-d arg="ZEN PLEASE" \
-H "Authorization: Bearer :access_token"
Device ID
Device name
Indicates if the device is currently connected to the cloud
Return value from the called function
POST /v1/devices/0123456789abcdef01234567/gong
{ "arg": "ZEN PLEASE" }
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"name": "gongbot",
"connected": true,
"return_value": 1
}
POST /v1/devices/0123456789abcdef01234567/gong
{ "format": "raw", "arg": "ZEN PLEASE" }
HTTP/1.1 200 OK
1
PUT /v1/devices/:deviceId/ping
This will ping a device, enabling you to see if your device is online or offline
devices:ping
Product ID or Slug. Product endpoint only.
$ curl https://api.particle.io/v1/devices/0123456789abcdef01234567/ping \
-X PUT \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/devices/0123456789abcdef01234567/ping \
-X PUT \
-H "Authorization: Bearer :access_token"
Indicates if the device is currently online
PUT /v1/devices/0123456789abcdef01234567/ping
HTTP/1.1 200 OK
{
"online": true,
"ok": true
}
PUT /v1/devices/:deviceId
Rename a device, either owned by a user or a product
devices:update
Device ID
Product ID or slug. Product endpoint only
The desired name for the device
$ curl -X PUT https://api.particle.io/v1/devices/0123456789abcdef01234567 \
-d name=phancy_photon \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/0123456789abcdef01234567 \
-d name=phancy_photon \
-H "Authorization: Bearer :access_token"
Device ID
Device name
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/devices/0123456789abcdef01234567
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"name": "phancy_photon"
"updated_at": "2017-03-10T20:21:49.059Z"
}
PUT /v1/devices/:deviceId
devices:update
Device ID
Product ID or slug. Product endpoint only
Notes that you would like to add to the device
$ curl -X PUT https://api.particle.io/v1/devices/0123456789abcdef01234567 \
-d notes="A fancy device note" \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/0123456789abcdef01234567 \
-d notes="A fancy device note" \
-H "Authorization: Bearer :access_token"
Device ID
Notes that have been added to the device
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/devices/0123456789abcdef01234567
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"notes": "A fancy device note",
"updated_at": "2017-03-10T20:21:49.059Z"
}
POST /v1/devices
Claim a new or unclaimed device to your account.
Device ID
Indicates you are requesting a device transfer from another user
$ curl https://api.particle.io/v1/devices \
-d id=0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/devices \
-d id=0123456789abcdef01234567 \
-d request_transfer=true \
-H "Authorization: Bearer :access_token"
Unique ID that represents the transfer
DELETE /v1/products/:productIdOrSlug/devices/:deviceId
Remove a device from a product and re-assign to a generic Particle product. This endpoint will unclaim the device if it is owned by a customer
.
devices:remove
Product ID or Slug
ID of the device to be removed
DELETE /v1/products/photon/devices/123abc
HTTP/1.1 204 NO CONTENT
DELETE /v1/devices/:deviceId
Remove ownership of a device. This will unclaim regardless if the device is owned by a user
or a customer
, in the case of a product.
When using this endpoint to unclaim a product device, the route looks slightly different:
DELETE /v1/products/:productIdOrSlug/devices/:deviceId/owner
Note the /owner
at the end of the route.
devices:release
ID of the device to be unclaimed
Product ID or Slug
$ curl -X DELETE https://api.particle.io/v1/devices/12345 \
-H "Authorization: Bearer :access_token"
# Note that the product endpoint requires adding "/owner" to the end of the route
$ curl -X DELETE https://api.particle.io/v1/products/:productIdOrSlug/devices/12345/owner \
-H "Authorization: Bearer :access_token"
DELETE /v1/devices/12345
HTTP/1.1 200 OK
{
"ok": true
}
PUT /v1/devices/:deviceId
Make the device conspicuous by causing its LED to flash in rainbow patterns
Device ID
1 to start shouting rainbows, 0 to stop
$ curl -X PUT https://api.particle.io/v1/devices/12345 \
-d signal=1 \
-H "Authorization: Bearer :access_token"
PUT /v1/devices/12345
HTTP/1.1 200 OK
{
"id": "12345",
"connected": true,
"signaling": true
}
PUT /v1/devices/:deviceId
Force enable OTA updates on this device.
devices:update
Device ID
true
to force enable updates, false
to unforce updates.
$ curl -X PUT https://api.particle.io/v1/devices/12345 \
-d firmware_updates_forced=true \
-H "Authorization: Bearer :access_token"
PUT /v1/devices/12345
HTTP/1.1 200 OK
{
"id": "12345",
"firmware_updates_forced": true
}
GET /v1/serial_numbers/:serial_number
Return the device ID and SIM card ICCD (if applicable) for a device by serial number. This API can look up devices that you have not yet added to your product and is rate limited to 50 requests per hour. Once you've imported your devices to your product you should instead use the list devices in a product API and filter on serial number. No special rate limits apply to that API.
The serial number printed on the barcode of the device packaging.
$ curl https://api.particle.io/v1/serial_numbers/E26AAA111111111 \
-H "Authorization: Bearer :access_token"
The ID of the device associated with this device
The ICCID number (SIM card ID number) of the SIM card associated with this device
GET /v1/serial_numbers/E26AAA111111111
HTTP/1.1 200 OK
{
"ok": true,
"deviceID": "0123456789abcdef01234567",
"iccid": "8934076500002589174"
}
POST /v1/diagnostics/:deviceId/update
Refresh diagnostic vitals for a single device. This will instruct the device to publish a new event to the Device Cloud containing a device vitals payload. This is an asynchronous request: the HTTP request returns immediately after the request to the device is sent. In order for the device to respond with a vitals payload, it must be online and connected to the Device Cloud.
The device will respond by publishing an event named spark/device/diagnostics/update
. See the description of
the device vitals event.
Device ID
Product ID or slug. Product endpoint only
$ curl -X POST https://api.particle.io/v1/diagnostics/0123456789abcdef01234567/update \
-H "Authorization: Bearer :access_token"
$ curl -X POST https://api.particle.io/v1/products/:productIdOrSlug/diagnostics/0123456789abcdef01234567/update \
-H "Authorization: Bearer :access_token"
GET /v1/diagnostics/0123456789abcdef01234567/update
HTTP/1.1 202
{
"ok": true
}
PUBLISH spark/device/diagnostics/update
The device publishes a Particle event named spark/device/diagnostics/update
in response to
a Device Cloud request to refresh device vitals. The body of the event will contain the diagnostic vitals for the device. The payload of the diagnostics payload will differ per device type.
devices.diagnostics:update
The device vitals payload information
Device vitals data containing diagnostics reported directly from the device
Represents diagnostics on all layers of the network stack that impact the device's ability to communicate with the Device Cloud
Cellular network information
The human readible form of the access technology. Possible values are 2G, 3G, LTE
The name of the company operating the tower on which the device is currently connected
A globally unique identifier that can be used to geographically locate the tower to which a device is connected
MCC. Can be used together with the Mobile Network Code (MNC) to determine the mobile network operator (i.e. mcc:310 and mnc:410 is AT&T)
MNC. Can be used together with the Mobile Country Code (MCC) to determine the mobile network operator (i.e. mcc:310 and mnc:410 is AT&T). This is a string because leading zeros are significant for MNC
a unique number identifying the current location area. A location area is a set of base stations that are grouped together to optimize signalling
a generally unique number used to identify each Base Transceiver Station (BTS) or sector of a BTS within a location area code
The signal strength and quality metrics
The detailed radio access technology, which determines the range of good signal strength and quality. Possible values are Wi-Fi, GSM, EDGE, UMTS, CDMA, LTE, LTE Cat-M1, LTE Cat-NB1
Measure of the current radio network strength in % (0-100)
Always %
Signal strength raw value specific to the access technology
Always dbM
The algorithm used to calculate signal strength. Possible values are RSSI (Wi-Fi), RXLEV (2G), RSCP (3G), RSRP (LTE)
Measure of the current radio connection quality in % (0-100)
Always %
Signal quality raw value specific to the access technology
Always dB
The algorithm used to calculate signal quality. Possible values are SNR (Wi-Fi), RXQUAL (2G), ECN0 (3G), RSRQ (LTE)
Statistics about the network
Status of the network connection. When receiving a vitals event through the Cloud it should always be connected. Possible values are turned_off, turning_on, disconnected, connecting, connected, disconnecting, turning_off
A platform-specific error code that is returned by the low-level Device OS function for the most recent network connectivity event
Count of network disconnects
Number of attempts required to establish a successful network connection
Last reason the network got disconnected. Possible values are none, error, user, network_off, listening, sleep, reset
Device Cloud communication information
Information on the state of the device's cloud connection
Status of the cloud connection. When receiving a vitals event through the Cloud it should always be connected. Possible values are disconnected, connecting, connected, disconnecting
A platform-specific error code that is returned by the low-level Device OS function for the most recent cloud connectivity event
Number of attempts required to establish a successful cloud connection
The number of unexpected disconnections from the cloud since the last reset
Last reason the cloud connection got disconnected. Possible values are none, error, user, network_disconnect, listening
Information regarding the underlying communication protocol
The number of CoAP messages sent by the device to the cloud
The number of times a CoAP message was resent by the device to the cloud due to the original message not being acknowledged
The number of CoAP messages that were resent the maximum number of times by the device, still not acknowledged by the cloud then dropped
The round-trip time of the last device to cloud message in milliseconds
Information regarding publish attempts from the device
The current count of rate limited publishes since the device was reset
Concerns sources of device power. This will only be populated for devices with on-board power management.
Information about batteries
Battery charge as a percent
The current charging state of the battery. Possible values are unknown, not_charging, charging, charged, discharging, fault, disconnected
An enumeration describing the current power source. Possible values are unknown, VIN, USB host, USB adapter, USB otg
Indicators of general device health and system status
The number of seconds the system has been running
Memory metrics for the device
User application static RAM + heap used
Total amount of RAM available on the device in bytes
Device vitals data containing diagnostics collected by the Particle Device Cloud on behalf of the device
Cloud to device information
The result of the last attempt to decode the vitals message from the device. Should always be ok. Possible values are ok, error
Information on the device's cloud session
Duration of the device session in seconds
Cloud-side metrics for device messages
The total number of Particle.publish events sent by the device
Information regarding the underlying communication protocol
The round-trip time of the last cloud to device message in milliseconds
{
"device": {
"network": {
"cellular": {
"radio_access_technology": "3G",
"operator": "AT&T Wireless Inc.",
"cell_global_identity": {
"mobile_country_code": 310,
"mobile_network_code": "410",
"location_area_code": 45997,
"cell_id": 20160117
}
},
"signal": {
"at": "UMTS",
"strength": 66.66,
"strength_units": "%",
"strengthv": -57,
"strengthv_units": "dBm",
"strengthv_type": "RSCP",
"quality": 75.51,
"quality_units": "%",
"qualityv": -6,
"qualityv_units": "dB",
"qualityv_type": "ECN0"
},
"connection": {
"status": "connected",
"error": 0,
"disconnects": 1,
"attempts": 1,
"disconnect_reason": "reset"
}
},
"cloud": {
"connection": {
"status": "connected",
"error": 0,
"attempts": 2,
"disconnects": 23,
"disconnect_reason": "error"
},
"coap": {
"transmit": 412,
"retransmit": 3,
"unack": 0,
"round_trip": 1594
},
"publish": {
"rate_limited": 0
}
},
"power": {
"battery": {
"charge": 87.12,
"state": "not_charging"
},
"source": "VIN"
},
"system": {
"uptime": 2567461,
"memory": {
"used": 36016,
"total": 113664
}
}
},
"service": {
"device": {
"status": "ok"
},
"cloud": {
"uptime": 82925,
"publish": {
"sent": 1384
}
},
"coap": {
"round_trip": 920
}
}
}
GET /v1/diagnostics/:deviceId/last
Returns the last device vitals payload sent by the device to the Device Cloud.
devices.diagnostics:get
Device ID
Product ID or slug. Product endpoint only
$ curl https://api.particle.io/v1/diagnostics/0123456789abcdef01234567/last \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/diagnostics/0123456789abcdef01234567/last \
-H "Authorization: Bearer :access_token"
The last known device vitals object
Timestamp of when the diagnostic vitals record was reported
ID of the device
Full device vitals payload. See the device vitals documentation for the structure of this object.
GET /v1/diagnostics/0123456789abcdef01234567/last
HTTP/1.1 200 OK
{
"diagnostics": {
"updated_at": "2017-12-19T12:37:07.318Z",
"deviceID": "0123456789abcdef01234567",
"payload": {
... the device vitals event payload.
}
}
}
GET /v1/diagnostics/:deviceId
Returns all stored device vital records sent by the device to the Device Cloud. Device vitals records will expire after 1 month.
Optionally set to text/csv
to return historic device vitals as a CSV
devices.diagnostics:get
Device ID
Product ID or slug. Product endpoint only
Oldest diagnostic to return, inclusive. Date in ISO8601 format.
Newest diagnostic to return, exclusive. Date in ISO8601 format.
$ curl https://api.particle.io/v1/diagnostics/0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/diagnostics/0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/diagnostics/0123456789abcdef01234567?start_date=2017-12-18T12:37:07.318Z&end_date=2017-12-20T12:37:07.318Z" \
-H "Authorization: Bearer :access_token"
An array of stored device vitals records. See the device vitals documentation for the structure of the payload for each object in the array.
GET /v1/diagnostics/0123456789abcdef01234567/
HTTP/1.1 200 OK
{
"diagnostics": [
{
"updated_at": "2017-12-19T12:37:07.318Z",
"deviceID": "0123456789abcdef01234567",
"payload": {
... the device vitals event payload.
}
},
...
]
}
when invalid start/end dates are provided
GET /v1/diagnostics/0123456789abcdef01234567?end_date=invalid-date
HTTP/1.1 200 OK
{
"error": "bad_request",
"description": "start_date and end_date must be ISO8601 formatted",
}
GET /v1/diagnostics/0123456789abcdef01234567?end_date=invalid-date
HTTP/1.1 200 OK
{
"error": "bad_request",
"description": "start_date must not be more than than 30 days ago",
}
GET /v1/sims/:iccid/status
Get cellular network status for a given device. Kicks off a long running task that checks if the device/SIM has an active data session with a cell tower. Values for keys in the sim_status
object will be null
until the task has finished.
Poll the endpoint until meta.state
is complete
. At this point, the sim_status
object will be populated.
Note that responses are cached by the cellular network providers. This means that on occasion, the real-time status of the device/SIM may not align with the results of this test.
sims.status:get
The ICCID of the desired SIM
Product ID or slug. Product endpoint only
$ curl https://api.particle.io/v1/sims/1234/status \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims/1234/status \
-H "Authorization: Bearer :access_token"
Whether the request was successful
Meta information about the task
UTC timestamp of when the task was kicked off
UTC timestamp when the task results will expire
UTC timestamp of the suggested time after which to check status again
Set to async
to communicate an asynchronous request
the state of the task. Can be pending
or complete
.
the id of the task
Status information about the SIM
Whether the device/SIM has an active data session with a cell tower (both GSM and data connection are true
)?
Whether the device/SIM has a GSM connection?
Whether the device/SIM has a GPRS/LTE/Data connection?
GET /v1/sims/:iccid/status
HTTP/1.1 202
{
"ok": true,
"meta": {
"created_at": "2018-05-29T19:31:55.000-06:00",
"expires_at": "2018-05-29T19:34:55.000-06:00",
"check_again_after": "2018-05-29T19:32:05.450-06:00",
"state": "pending",
"method": "async",
"task_id": "1234abcd"
},
"sim_status": {
"connected": true,
"gsm_connection": true,
"data_connection": true,
}
}
GET /user
Return the user resource for the currently authenticated user.
$ curl https://api.particle.io/v1/user -H "Authorization: Bearer :access_token"
Email address for current user
Subscriptions for SIM cards and products
Includes whether MFA is enabled
An object that contains a first_name, last_name, and business_account
Number of devices that count against the Wi-Fi device cap
Number of devices that count against the cellular device cap
GET /v1/user
HTTP/1.1 200 OK
{
"username": "testuser@particle.io",
"subscription_ids": [],
"account_info": {
"first_name": "Test",
"last_name": "User",
"business_account": false
},
scim_provisioned: false,
no_password: false,
"mfa": {
"enabled": false
},
"wifi_device_count": 0,
"cellular_device_count": 0
}
PUT /user
Update the logged-in user. Allows changing email, password and other account information.
The new password
The new account email address
The new account info
The current password. Required to change username or password
Invalidate all access tokens for user
$ curl -X PUT https://api.particle.io/v1/user \
-d "password=I'm a really long password that no one would guess" \
-d "current_password=My current password" \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/user \
-d "username=testuser@example.com" \
-d "current_password=My current password" \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/user \
-d "account_info[first_name]=Test" \
-d "account_info[last_name]=User" \
-H "Authorization: Bearer :access_token"
PUT /v1/user
HTTP/1.1 200 OK
{
"ok": true,
"message": "User's password updated."
}
PUT /user
Delete the logged-in user. Allows removing user account and artifacts from Particle system
Current password verification
$ curl -X DELETE https://api.particle.io/v1/user \
-d "password=mypassword" \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE https://api.particle.io/v1/user \
-d "password=mypassword" \
-H "Authorization: Bearer :access_token"
PUT /v1/user
HTTP/1.1 200 OK
{
"ok": true,
"message": "User's account has been deleted."
}
POST /user/password-reset
Create a new password reset token and send the user an email with the token. This endpoint is rate-limited to prevent abuse.
Note: This endpoint does not require an access token.
$ curl -X POST https://api.particle.io/v1/user/password-reset \
-d username=forgetful-john@example.com
POST /v1/user/password-reset
HTTP/1.1 200 OK
{
"ok": true,
"message": "Password reset email sent."
}
POST /v1/products/:productIdOrSlug/devices
Approve a quarantined device. This will immediately release the device from quarantine and allow it to publish events, receive firmware updates, etc.
devices:import
Product ID or Slug
ID of the device to be denied
POST /v1/products/photon/devices
{ "id": "123abc" }
HTTP/1.1 200 OK
DELETE /v1/products/:productIdOrSlug/devices/:deviceId
Deny a quarantined device
devices:remove
Product ID or Slug
ID of the device to be denied
Flag indicating you wish to deny this device, instead of removing an already approved device.
DELETE /v1/products/photon/devices/123abc
{ deny: true }
HTTP/1.1 204 NO CONTENT
GET /v1/sims
Get a list of the SIM cards owned by an individual or a product. The product endpoint is paginated, by default returns 25 SIM card records per page.
sims:list
Product ID or slug. Product endpoint only
Filter results to SIMs with this ICCID (partial matching)
Filter results to SIMs with this associated device ID (partial matching)
Filter results to SIMs with this associated device name (partial matching)
Current page of results
Records per page
$ curl https://api.particle.io/v1/sims \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims \
-H "Authorization: Bearer :access_token"
An array of SIM card objects
ICCID of the SIM
Number of times the SIM has been activated
The ISO Alpha-2 code of the country where the SIM card is based
The monthly rate of the 1 MB data plan for this SIM card, in cents
Number of times the SIM has been deactivated
Timestamp of the first activation date of the SIM card
Timestamp of the last activation date of the SIM card
The method used to activate the SIM card. Internal use only, will be deprecated
The last state change of the SIM card
Whether the last action change resulted in an error. Set to "yes" or "no"
MSISDN number of the Ublox modem
The per-MB overage rate for this SIM card, in cents
The current connectivity status of the SIM card
Data plan type. Internal use only, will be deprecated
Timestamp representing the last time the SIM was updated
The ID of the user who owns the SIM card
The ID of the product who owns the SIM card
The Telefony provider for the SIM card's connectivity
The device ID of the SIM card's last associated device
The device name of the SIM card's last associated device
An object containing the total number of pages of records Product endpoint only
GET /v1/sims
HTTP/1.1 200 OK
{
"sims": [
{
"_id":"8934076500002589174",
"activations_count":1,
"base_country_code":"US",
"base_monthly_rate":299,
"deactivations_count":0,
"first_activated_on":"2017-01-27T23:10:16.994Z",
"last_activated_on":"2017-01-27T23:10:16.994Z",
"last_activated_via":"user_setup",
"last_status_change_action":"activate",
"last_status_change_action_error":"no",
"msisdn":"345901000485300",
"overage_monthly_rate":99,
"status":"active",
"stripe_plan_slug":"KickstarterElectronPlan",
"updated_at":"2017-01-27T23:10:22.622Z",
"user_id":"5580999caf8bad191600019b",
"carrier":"telefonica",
"last_device_id":"123abc",
"last_device_name":"foo_bar_baz"
},
...
]
}
GET /v1/sims/:iccid
Retrieve a SIM card owned by an individual or a product.
sims:get
Filter results to SIMs with this ICCID (partial matching) Product endpoint only
Product ID or slug. Product endpoint only
$ curl https://api.particle.io/v1/sims \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims \
-H "Authorization: Bearer :access_token"
The SIM card data object
ICCID of the SIM
Number of times the SIM has been activated
The ISO Alpha-2 code of the country where the SIM card is based
The monthly rate of the 1 MB data plan for this SIM card, in cents
Number of times the SIM has been deactivated
Timestamp of the first activation date of the SIM card
Timestamp of the last activation date of the SIM card
The method used to activate the SIM card. Internal use only, will be deprecated
The last state change of the SIM card
Whether the last action change resulted in an error. Set to "yes" or "no"
MSISDN number of the Ublox modem
The per-MB overage rate for this SIM card, in cents
The current connectivity status of the SIM card
Data plan type. Internal use only, will be deprecated
Timestamp representing the last time the SIM was updated
The ID of the user who owns the SIM card
The ID of the product who owns the SIM card
The Telefony provider for the SIM card's connectivity
The device ID of the SIM card's last associated device
The device name of the SIM card's last associated device
Particle username for the user who claimed this SIM card
GET /v1/sims/8934076500002589174
HTTP/1.1 200 OK
{
{
"_id":"8934076500002589174",
"activations_count":1,
"base_country_code":"US",
"base_monthly_rate":299,
"deactivations_count":0,
"first_activated_on":"2017-01-27T23:10:16.994Z",
"last_activated_on":"2017-01-27T23:10:16.994Z",
"last_activated_via":"user_setup",
"last_status_change_action":"activate",
"last_status_change_action_error":"no",
"msisdn":"345901000485300",
"overage_monthly_rate":99,
"status":"active",
"stripe_plan_slug":"KickstarterElectronPlan",
"updated_at":"2017-01-27T23:10:22.622Z",
"user_id":"5580999caf8bad191600019b",
"carrier":"telefonica",
"last_device_id":"123abc",
"last_device_name":"foo_bar_baz",
"owner": "someone@particle.io"
}
}
GET /v1/sims/:iccid/data_usage
Get SIM card data usage for the current billing period, broken out by day. Note that date usage reports can be delayed by up to 1 hour.
The ICCID of the desired SIM
Product ID or slug. Product endpoint only
$ curl https://api.particle.io/v1/sims/1234/data_usage \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims/1234/data_usage \
-H "Authorization: Bearer :access_token"
ICCID of the SIM
An array of data usage by day
The date of the usage day
Megabytes used in the usage day
Total megabytes used in the billing period, inclusive of this usage day
GET /v1/sims/:iccid/data_usage
HTTP/1.1 200 OK
{
"iccid":"8934076500002589174",
"usage_by_day": [
{
"date":"2017-02-24",
"mbs_used":0.98,
"mbs_used_cumulative":0.98
},
{
"date":"2017-02-25",
"mbs_used":0.50,
"mbs_used_cumulative":1.48
},
...
]
}
GET /v1/products/:productIdOrSlug/sims/data_usage
Get fleet-wide SIM card data usage for a product in the current billing period, broken out by day. Daily usage totals represent an aggregate of all SIM cards that make up the product. Data usage reports can be delayed until the next day, and occasionally by several days.
sims.usage:get
Product ID or slug
$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims/data_usage \
-H "Authorization: Bearer :access_token"
The total number of megabytes consumed by the fleet in the current billing period
The total number of active SIM cards in the product fleet. SIM cards that have been paused due to reaching their monthly data limit are included in this total.
An array of data usage by day
The date of the usage day
Megabytes used in the usage day
Total megabytes used in the billing period, inclusive of this usage day
GET /v1/products/:productIdOrSlug/sims/data_usage
HTTP/1.1 200 OK
{
"total_mbs_used":200.00,
"total_active_sim_cards":2000,
"usage_by_day": [
{
"date":"2017-03-01",
"mbs_used":100.00,
"mbs_used_cumulative":100.00
},
{
"date":"2017-03-02",
"mbs_used":100.00,
"mbs_used_cumulative":200.00
},
...
]
}
PUT /v1/sims/:iccid
Activates a SIM card for the first time.
Can not be used to activate Product SIM cards. Use the product import endpoint instead.
The ICCID of the SIM to update
Set to activate
to trigger SIM activation
$ curl -X PUT https://api.particle.io/v1/sims/1234 \
-d action=activate \
-H "Authorization: Bearer :access_token"
PUT /v1/sims/12345
HTTP/1.1 200 OK
POST /v1/products/:productIdOrSlug/sims
Import a group of SIM cards into a product. SIM cards will be activated upon import. Either pass an array of ICCIDs or include a file containing a list of SIM cards.
Import and activation will be queued for processing. You will receive an email with the import results when all SIM cards have been processed.
Importing a SIM card associated with a device will also import the device into the product.
sims:import
Product ID or slug
An array of SIM ICCIDs to import
A .txt file containing a single-column list of ICCIDs
$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims \
-d sims[]=8934076500002586220 \
-H "Authorization: Bearer :access_token"
POST /v1/products/:productIdOrSlug/sims
HTTP/1.1 200 OK
{
ok: true
}
PUT /v1/sims/:iccid
Deactivates a SIM card, disabling its ability to connect to a cell tower. Devices with deactivated SIM cards are not billable.
sims:update
The ICCID of the SIM to update
Product ID or slug. Product endpoint only
Set to deactivate
to trigger SIM deactivation
$ curl -X PUT https://api.particle.io/v1/sims/1234 \
-d action=deactivate \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/sims/1234 \
-d action=deactivate \
-H "Authorization: Bearer :access_token"
PUT /v1/sims/12345
HTTP/1.1 200 OK
PUT /v1/sims/:iccid
Re-enables a SIM card to connect to a cell tower. Do this if you'd like to reactivate a SIM that you have deactivated.
sims:update
sims:update
The ICCID of the SIM to update
Product ID or slug. Product endpoint only
Set to reactivate
to trigger SIM reactivation
$ curl -X PUT https://api.particle.io/v1/sims/1234 \
-d action=reactivate \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/sims/1234 \
-d action=reactivate \
-H "Authorization: Bearer :access_token"
PUT /v1/sims/12345
HTTP/1.1 200 OK
DELETE /v1/sims/:iccid
Remove a SIM card from an account, disassociating the SIM card from a user or a product. The SIM will also be deactivated.
Once the SIM card has been released, it can be claimed by a different user, or imported into a different product.
sims:remove
The ICCID of the desired SIM
Product ID or slug. Product endpoint only
$ curl -X DELETE https://api.particle.io/v1/sims/1234 \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE https://api.particle.io/v1/products/:productIdOrSlug/sims/1234 \
-H "Authorization: Bearer :access_token"
DELETE /v1/sims/1234
HTTP/1.1 204 No Content
DELETE /v1/sims/1234
HTTP/1.1 202 Accepted
GET /v1/events/:eventPrefix
Open a stream of Server Sent Events for all events. for your devices matching the filter.
Note that as of April 2018, the event prefix filter is required. It was optional before.
Filters the stream to only events starting with the specified prefix. The event prefix filter is required for this endpoint.
$ curl https://api.particle.io/v1/events/temp \
-H "Authorization: Bearer :access_token"
event name
event data in JSON format
GET /v1/events/temp
HTTP/1.1 200 OK
:ok
event: temperature
data: {"data":"25.34","ttl":"60","published_at":"2015-07-18T00:12:18.174Z","coreid":"0123456789abcdef01234567"}
GET /v1/events
HTTP/1.1 400 Bad Request
{ ok: false, error: "event prefix filter is required" }
GET /v1/devices/events/:eventPrefix
Open a stream of Server Sent Events for all events for your devices.
Filters the stream to only events starting with the specified prefix. Omit to get all events.
$ curl https://api.particle.io/v1/devices/events \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/devices/events/temp \
-H "Authorization: Bearer :access_token"
event name
event data in JSON format
GET /v1/devices/events
HTTP/1.1 200 OK
:ok
event: temperature
data: {"data":"25.34","ttl":"60","published_at":"2015-07-18T00:12:18.174Z","coreid":"0123456789abcdef01234567"}
GET /v1/devices/:deviceId/events/:eventPrefix
Open a stream of Server Sent Events for all events for the specified device.
Device ID
Filters the stream to only events starting with the specified prefix
$ curl https://api.particle.io/v1/devices/0123456789abcdef01234567/events \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/devices/0123456789abcdef01234567/events/temp \
-H "Authorization: Bearer :access_token"
event name
event data in JSON format
GET /v1/devices/0123456789abcdef01234567/events
HTTP/1.1 200 OK
:ok
event: temperature
data: {"data":"25.34","ttl":"60","published_at":"2015-07-18T00:12:18.174Z","coreid":"0123456789abcdef01234567"}
GET /v1/products/:productIdOrSlug/events/:eventPrefix
Open a stream of Server Sent Events for all events for a product.
events:get
Product ID or slug
Filters the stream to only events starting with the specified prefix
$ curl https://api.particle.io/v1/products/photon/events \
-H "Authorization: Bearer :access_token"
event name
event data in JSON format
GET /v1/products/photon/events
HTTP/1.1 200 OK
:ok
event: temperature
data: {"data":"25.34","ttl":"60","published_at":"2015-07-18T00:12:18.174Z","coreid":"0123456789abcdef01234567"}
POST /v1/devices/events
Publish an event
Event name
Event data
How long the event should persist
$ curl https://api.particle.io/v1/devices/events \
-d "name=myevent" \
-d "data=Hello World" \
-d "ttl=60" \
-H "Authorization: Bearer :access_token"
$ particle publish myevent "Hello World"
POST /v1/devices/events
HTTP/1.1 200 OK
{
"ok": true
}
POST /v1/products/:productIdOrSlug/events
Publish an event that is sent to the product's event stream
events:send
Product ID or slug.
Event name
Event data
How long the event should persist
$ curl "https://api.particle.io/v1/products/:productIdOrSlug/events" \
-d "name=myevent" \
-d "data=Hello World" \
-d "ttl=60" \
-H "Authorization: Bearer :access_token"
POST /v1/products/:productIdOrSlug/events
HTTP/1.1 200 OK
{
"ok": true
}
Also note:
Particle.publish
returns true, there is no guarantee that any recipient (another device, webhook, or SSE) will receive it.Particle.publish
returns false, the event will still be received by the cloud later. This occurs because the 20-second timeout is reached, so false is returned, but the event is still buffered in Device OS and will be retransmitted if the reconnection to the cloud succeeds.Two common ways Particle devices can trigger external services are webhooks and Server-Sent Events (SSE).
The SSE event stream works by having your server make an outbound https (encrypted) connection to the Particle API service. This connection is kept open, and if new events arrive, they are immediately passed down this stream. There are a number of advantages to this:
While this sounds great, there are some issues that can occur that make it less than ideal for large device fleets and make webhooks more attractive:
SSE | Webhooks |
---|---|
Works from behind a firewall | Requires a public IP address |
Encrypted without a SSL certificate | Requires a SSL certificate for the server to support https |
Best if lost events are not critical | Event delivery is more reliable |
Only allows a single server | Can use load balancing and redundant servers |
When using SSE, we recommend using the particle-api-js library with node.js, however any language can be used. We recommend using a good, well-tested SSE library as there are some things to beware of when implementing the SSE protocol:
There is a limit of 100 requests to open an SSE connection in each 5 minute period per public IP address. If rate limiting occurs, you will get a 529 error and you must wait before retrying the connection or you will never be able to successfully connect again. There is also a limit of 100 simultaneous SSE connections from each public IP address. This is not separated by device, access token, etc.; it applies to the public IP address the requests come from.
Because of the simultaneous connection limit, if you want to subscribe to multiple events, you should establish one SSE connection to handle all events, and filter the results for the events that you want to handle. While this seems less efficient, it is the preferred method because the overhead of handling multiple SSE sessions is far higher than the incremental overhead of sending many events across a single event stream. Using a common prefix to group multiple events that need to be received from a single SSE event stream is also a good technique to use if possible.
POST /v1/integrations
A webhook is a flexible type of integration that allows you to interact with a wide variety of external tools and services. Create a webhook either for devices you own as a Particle developer, or for your product fleet. For more info, check out the webhooks guide.
integrations:create
Product ID or slug. Product endpoint only.
Must be set to Webhook
The name of the Particle event that should trigger the webhook
The web address that will be targeted when the webhook is triggered
A human-readable description of the webhook. Defaults to "{event} for {domain}" if omitted.
Type of web request triggered by the webhook that can be set to GET, POST, PUT, or DELETE
Limits the webhook triggering to a single device
Send a custom body along with the HTTP request
Send custom data as JSON with the request. This will change the Content-Type header of the request to application/json
Send custom data as a form with the request by including key/value pairs. This will change the Content-Type header of the request to application/x-www-form-urlencoded
Send query parameters in the URL of the request by including key/value pairs
Add an HTTP basic auth header by including a JSON object with username/password set
Add custom HTTP headers by including key/value pairs
Customize the webhook response event name that your devices can subscribe to
Customize the webhook error response event name that your devices can subscribe to
Customize the webhook response body that your devices can subscribe to
Set to true
to not add the triggering Particle event's data to the webhook request
Set to true
to stop events from being sent to this webhook
Set to false
to skip SSL certificate validation of the target URL
The template that was used to create this webhook
$ curl https://api.particle.io/v1/integrations \
-d integration_type=Webhook \
-d event=hello \
-d url=https://samplesite.com \
-d requestType=POST \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations \
-d integration_type=Webhook \
-d event=hello \
-d url=https://samplesite.com \
-d requestType=POST \
-H "Authorization: Bearer :access_token"
Webhook ID
Web address that will be targeted when the webhook is triggered
Timestamp of when the webhook was created
Should be set to Webhook
Particle API endpoint to GET info on the webhook
POST /v1/webhooks
HTTP/1.1 201 Created
{
"ok": true
"id": "12345",
"url": "https://samplesite.com",
"event": "hello",
"name": "hello for samplesite.com",
"created_at": "2016-04-28T17:06:33.123Z",
"hookUrl": "https://api.particle.io/v1/webhooks/12345"
}
POST /v1/integrations
Enable an integration with Azure IoT Hub. For more details, check out the tutorial.
integrations:create
Product ID or slug. Product endpoint only.
Must be set to AzureIotHub
The name of the Particle event that should trigger the integration
The name of your Azure IoT Hub
A human-readable description of the webhook. Defaults to "{event} for {hub_name}" if omitted.
The name of the shared access policy used for authentication
The shared access policy key used for authentication
Limits the integration triggering to a single device
A custom JSON payload to send along with the request
Set to true
to stop events from being sent to this integration
$ curl https://api.particle.io/v1/integrations \
-d integration_type=AzureIotHub \
-d event=hello \
-d hub_name=myHubName \
-d policy_name=particle \
-d policy_key=123abc \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations \
-d integration_type=AzureIotHub \
-d event=hello \
-d hub_name=myHubName \
-d policy_name=particle \
-d policy_key=123abc \
-H "Authorization: Bearer :access_token"
Integration ID
Timestamp of when the integration was created
Should be set to AzureIotHub
URL to fetch information about the integration
The name of your Azure IoT Hub
The name of the shared access policy used for authentication
The shared access policy key used for authentication
POST /v1/integrations
HTTP/1.1 201 Created
{
"id":"1",
"event":"foo",
"created_at":"2017-03-16T19:54:54.570Z",
"integration_type":"AzureIotHub",
"hub_name":"your-iot-hub-name",
"name": "foo for yout-iot-hub-name",
"policy_name":"iothubowner",
"policy_key": "123abc",
"ok":true,
"integrationUrl": "https://api.particle.io/v1/integrations/1"
}
POST /v1/integrations
Enable an integration with Google Cloud Platform. For more details, check out the tutorial.
integrations:create
Product ID or slug. Product endpoint only.
Must be set to GoogleCloudPubSub
The name of the Particle event that should trigger the integration
The Google Cloud Pub Sub topic name for publishing messages
A human-readable description of the webhook. Defaults to "{event} for {topic}" if omitted.
Limits the integration triggering to a single device
Set to true
to stop events from being sent to this integration
$ curl https://api.particle.io/v1/integrations \
-d integration_type=GoogleCloudPubSub \
-d event=hello \
-d topic=your/topic/name \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations \
-d integration_type=GoogleCloudPubSub \
-d event=hello \
-d topic=your/topic/name \
-H "Authorization: Bearer :access_token"
Integration ID
Timestamp of when the integration was created
Should be set to GoogleCloudPubSub
URL to fetch information about the integration
The Google Cloud Pub Sub topic name for publishing messages
POST /v1/integrations
HTTP/1.1 201 Created
{
"id":"1",
"event":"foo",
"created_at":"2017-03-16T19:54:54.570Z",
"integration_type":"GoogleCloudPubSub",
"topic": "your/topic/name",
"name": "foo for name",
"ok":true,
"integrationUrl": "https://api.particle.io/v1/integrations/1"
}
POST /v1/integrations
Enable an integration with Google Maps. For more details, check out the tutorial.
integrations:create
Product ID or slug. Product endpoint only.
Must be set to GoogleMaps
The name of the Particle event that should trigger the integration
A human-readable description of the webhook. Defaults to "{event} for Google Maps" if omitted.
Your Google Maps Geolocation API key. Check out these docs for details
Limits the integration triggering to a single device
Set to true
to stop events from being sent to this integration
$ curl https://api.particle.io/v1/integrations \
-d integration_type=GoogleMaps \
-d event=hello \
-d api_key=123abc \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations \
-d integration_type=GoogleMaps \
-d event=hello \
-d api_key=123abc \
-H "Authorization: Bearer :access_token"
Integration ID
Timestamp of when the integration was created
Your Google Maps Geolocation API key
Should be set to GoogleCloudPubSub
URL to fetch information about the integration
POST /v1/integrations
HTTP/1.1 201 Created
{
"id":"1",
"event":"foo",
"name': "foo for Google Maps",
"created_at":"2017-03-16T19:54:54.570Z",
"integration_type":"GoogleMaps",
"ok":true,
"api_key": "123abc",
"integrationUrl": "https://api.particle.io/v1/integrations/1"
}
PUT /v1/integrations/:integrationId
Edit a Webhook. Subsequent triggering of this integration will be sent with the new attributes.
The configuration replaces the entire previous webhook configuration. It does not merge in changes.
integrations:update
The ID of the desired integration
Product ID or slug. Product endpoint only.
The name of the Particle event that should trigger the webhook
Limits the webhook triggering to a single device
The web address that will be targeted when the webhook is triggered
A human-readable description of the webhook
Type of web request triggered by the webhook that can be set to GET, POST, PUT, or DELETE
Send a custom body along with the HTTP request
Send custom data as JSON with the request. This will change the Content-Type header of the request to application/json
Send custom data as a form with the request by including key/value pairs. This will change the Content-Type header of the request to application/x-www-form-urlencoded
Send query parameters in the URL of the request by including key/value pairs
Add an HTTP basic auth header by including a JSON object with username/password set
Add custom HTTP headers by including key/value pairs
Customize the webhook response event name that your devices can subscribe to
Customize the webhook error response event name that your devices can subscribe to
Customize the webhook response body that your devices can subscribe to
Set to true
to not add the triggering Particle event's data to the webhook request
Set to true
to stop events from being sent to this webhook
Set to false
to skip SSL certificate validation of the target URL
The template that was used to create this webhook
$ curl -X PUT https://api.particle.io/v1/integrations/12345 \
-d event=foo \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345 \
-d event=foo \
-H "Authorization: Bearer :access_token"
An integration object.
PUT /v1/integrations/12345
HTTP/1.1 200 OK
{
"integration": {
"id":"12345",
"event":"foo",
"name": "Check weather",
"created_at":"2017-03-14T17:57:46.316Z",
"integration_type":"Webhook",
"url":"https://weather.com",
"requestType":"POST"
}
}
PUT /v1/integrations/:integrationId
Edit an Azure IoT Hub integration. Subsequent triggering of this integration will be sent with the new attributes.
The configuration replaces the entire previous webhook configuration. It does not merge in changes.
integrations:update
The ID of the desired integration
Product ID or slug. Product endpoint only.
The name of the Particle event that should trigger the integration
A human-readable description of the webhook
Limits the integration triggering to a single device
The name of your Azure IoT Hub
The name of the shared access policy used for authentication
The shared access policy key used for authentication
A custom JSON payload to send along with the request
Set to true
to stop events from being sent to this integration
$ curl -X PUT https://api.particle.io/v1/integrations/12345 \
-d event=foo \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345 \
-d event=foo \
-H "Authorization: Bearer :access_token"
An integration object.
PUT /v1/integrations/12345
HTTP/1.1 200 OK
{
"integration": {
"id":"12345",
"event":"foo",
"created_at":"2017-03-14T17:57:46.316Z",
"integration_type":"AzureIotHub",
"hub_name": "your_iot_hub",
"name": "Send to Azure",
"policy_name": "policy_name"
"policy_key": "123abc"
}
}
PUT /v1/integrations/:integrationId
Edit a Google Cloud platform integration. Subsequent triggering of this integration will be sent with the new attributes.
The configuration replaces the entire previous webhook configuration. It does not merge in changes.
integrations:update
The ID of the desired integration
Product ID or slug. Product endpoint only.
The name of the Particle event that should trigger the integration
A human-readable description of the webhook
Limits the integration triggering to a single device
The Google Cloud Pub Sub topic name for publishing messages
Set to true
to stop events from being sent to this integration
$ curl -X PUT https://api.particle.io/v1/integrations/12345 \
-d event=foo \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345 \
-d event=foo \
-H "Authorization: Bearer :access_token"
An integration object.
PUT /v1/integrations/12345
HTTP/1.1 200 OK
{
"integration": {
"id":"12345",
"event":"foo",
"created_at":"2017-03-14T17:57:46.316Z",
"integration_type":"GoogleCloudPubSub",
"name": "Send to Google",
"topic": "your/topic/name"
}
}
PUT /v1/integrations/:integrationId
Edit a Google Maps integration. Subsequent triggering of this integration will be sent with the new attributes.
The configuration replaces the entire previous webhook configuration. It does not merge in changes.
integrations:update
The ID of the desired integration
Product ID or slug. Product endpoint only.
The name of the Particle event that should trigger the integration
A human-readable description of the webhook
Limits the integration triggering to a single device
Your Google Maps Geolocation API key. Check out these docs for details
Set to true
to stop events from being sent to this integration
$ curl -X PUT https://api.particle.io/v1/integrations/12345 \
-d api_key=123abc \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345 \
-d api_key=123abc \
-H "Authorization: Bearer :access_token"
An integration object.
PUT /v1/integrations/12345
HTTP/1.1 200 OK
{
"integration": {
"id":"12345",
"event":"foo",
"created_at":"2017-03-14T17:57:46.316Z",
"integration_type":"GoogleMaps",
"name": "Send to Google Maps",
"api_key": "123abc"
}
}
GET /v1/integrations/:integrationId
Get a single integration. Pay special attention to the integration_type
attribute of each integration, which will let you know whether the integration is a
Webhook, an
Azure IoT Hub integration, a
Google Cloud Platform integration, or a
Google Maps integration.
integrations:get
The ID of the desired integration
Product ID or slug. Product endpoint only.
$ curl https://api.particle.io/v1/integrations/12345 \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345 \
-H "Authorization: Bearer :access_token"
An integration object. The object will vary in its attributes depending on integration type. For information on specific integration type response bodies, please see creation docs for Webhooks, Azure IoT Hub, and Google Cloud Platform.
Contains information about the last 10 HTTP request/responses sent from this integration. A useful debugging tool.
GET /v1/integrations/12345
HTTP/1.1 200 OK
{
"integration": {
"id":"12345",
"event":"eventName",
"name": "Check weather",
"created_at":"2017-03-14T17:57:46.316Z",
"logs": [...],
"integration_type":"Webhook",
"url":"https://weather.com",
"requestType":"POST"
}
}
GET /v1/integrations
List all integrations. Pay special attention to the integration_type
attribute of each integration, which will let you know whether the integration is a
Webhook, an
Azure IoT Hub integration, or a
Google Cloud Platform integration.
If you would like to only list webhooks (integrations with type: 'Webhook'
), you can use a slightly different endpoint:
GET /v1/webhooks
integrations:list
Product ID or slug. Product endpoint only.
$ curl https://api.particle.io/v1/integrations \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/webhooks \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/webhooks \
-H "Authorization: Bearer :access_token"
An array of integration objects. The object will vary in its attributes depending on integration type. For information on specific integration type response bodies, please see creation docs for Webhooks, Azure IoT Hub, and Google Cloud Platform.
GET /v1/integrations
HTTP/1.1 200 OK
[
{
"id":"12345",
"event":"eventName",
"created_at":"2017-03-14T17:57:46.316Z",
"integration_type":"Webhook",
"url":"https://weather.com",
"requestType":"POST"
}
]
POST /v1/integrations/:integrationId/test
Send a test event that triggers the integration. Helps build confidence that an integration is configured properly.
integrations:test
The ID of the desired integration
Product ID or slug. Product endpoint only.
Custom data to send with the test event. Defaults to "test-event" if omitted.
The device ID to test the integration with. Defaults to "api" if omitted.
$ curl https://api.particle.io/v1/integrations/12345/test \
-d data=my-data \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345/test \
-d data=my-data \
-H "Authorization: Bearer :access_token"
Whether the integration was able to receive a successful response from the target
The data returned by a successful integration test attempt
If unsuccessful, the error returned from the target
POST /v1/integrations/1234/test
HTTP/1.1 200 OK
{
pass: true,
data: null
}
DELETE /v1/integrations/:integrationId
Delete an integration and immediate stop it from triggering. The integration can belong to a user or to a product.
integrations:remove
The ID of the desired integration
Product ID or slug (only for product webhooks)
$ curl -X DELETE https://api.particle.io/v1/integrations/12345 \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE https://api.particle.io/v1/products/:productIdOrSlug/integrations/12345 \
-H "Authorization: Bearer :access_token"
DELETE /v1/webhooks
HTTP/1.1 204 No Content
If you watch your event stream, you may notice your devices publishing events that don't appear in your firmware. The cloud will automatically publish events in special situations that would be hard to monitor without an event.
When your device starts ("online") or stops ("offline") a session with the cloud, you'll see a 'spark/status' event.
# spark/status, online
{"name":"spark/status","data":"online","ttl":"60","published_at":"2015-01-01T14:29:49.787Z","coreid":"0123456789abcdef01234567"}
# spark/status, offline
{"name":"spark/status","data":"offline","ttl":"60","published_at":"2015-01-01T14:31:49.787Z","coreid":"0123456789abcdef01234567"}
Offline events occur if the device gracefully disconnects from the cloud. If you remove the power to a device, the offline event will occur at approximately two times the default keep alive value. For the P2, Photon 2, and Argon, 2 × 25 seconds = 50 seconds. For cellular devices, 2 × 23 minutes = 46 minutes.
If the device comes online and the cloud did not know it was previously offline, the offline will be generated immediately before the online, not when the actual offline occurred, since it would be impossible to know.
If your device is running an app that needs a particular version of Device OS, your device may come online and report that it's in Safe Mode. In this case, your device is waiting to run your app until it has received an update. Some products can receive system updates automatically while in safe mode, but others like the Electron prevent this to save you costs on bandwidth. If you do get an automatic update, you may see a "spark/safe-mode-updater/updating" event.
# spark/status/safe-mode
{"name":"spark/status/safe-mode","data":"{ .. a bunch of data from your device about the system parts ...","ttl":"60","published_at":"2016-01-01T14:40:0.000Z","coreid":"0123456789abcdef01234567"}
{"name":"spark/status/safe-mode","data":"{\"f\":[],\"v\":{},\"p\":6,\"m\":[{\"s\":16384,\"l\":\"m\",\"vc\":30,\"vv\":30,\"f\":\"b\",\"n\":\"0\",\"v\":4,\"d\":[]},{\"s\":262144,\"l\":\"m\",\"vc\":30,\"vv\":30,\"f\":\"s\",\"n\":\"1\",\"v\":11,\"d\":[]},{\"s\":262144,\"l\":\"m\",\"vc\":30,\"vv\":30,\"f\":\"s\",\"n\":\"2\",\"v\":7,\"d\":[{\"f\":\"s\",\"n\":\"1\",\"v\":7,\"_\":\"\"}]},{\"s\":131072,\"l\":\"m\",\"vc\":30,\"vv\":26,\"u\":\"F3380CF3018C104BA3BD9438EA921A1ABF315E8063318FDDDCDBE10FED044BEB\",\"f\":\"u\",\"n\":\"1\",\"v\":3,\"d\":[{\"f\":\"s\",\"n\":\"2\",\"v\":11,\"_\":\"\"}]},{\"s\":131072,\"l\":\"f\",\"vc\":30,\"vv\":0,\"d\":[]}]}","ttl":"60","published_at":"2015-01-01T14:40:0.000Z","coreid":"0123456789abcdef01234567"}
# spark/safe-mode-updater/updating
{"name":"spark/safe-mode-updater/updating","data":"2","ttl":"60","published_at":"2016-01-01T14:41:0.000Z","coreid":"particle-internal"}
You can copy and paste the raw event JSON data from a safe-mode event into the Device Inspect Tool to decode the data.
As updates are being delivered via the cloud to your device, you may see some events published by the cloud to help
you monitor the update, typically started
and success
but could also be failed
.
{"name":"spark/flash/status","data":"started","ttl":"60","published_at":"2016-02-09T14:43:05.606Z","coreid":"0123456789abcdef01234567"}
{"name":"spark/flash/status","data":"success","ttl":"60","published_at":"2016-02-09T14:38:18.978Z","coreid":"0123456789abcdef01234567"}
{"name":"spark/flash/status","data":"failed","ttl":"60","published_at":"2016-02-09T14:43:11.732Z","coreid":"0123456789abcdef01234567"}
After you've flashed a new app to your device, you may see an "app-hash" event. This is a unique hash corresponding to that exact app binary. This hash can help confirm a flash succeeded and your new app is running, and also help you track exactly which version of which app is running on your device. This is only published when it is different from the previous session.
# spark/device/app-hash
{"name":"spark/device/app-hash","data":"2BA4E71E840F596B812003882AAE7CA6496F1590CA4A049310AF76EAF11C943A","ttl":"60","published_at":"2016-02-09T14:43:13.040Z","coreid":"2e0041000447343232363230"}
These events are used for controlling OTA updates.
particle/device/updates/enabled
(true or false). Sent by the device in response to System.enableUpdates()
or System.disableUpdates()
.
particle/device/updates/forced
(true or false). Sent by the device when a forced update is requested. This is used to prevent a race condition during forced updates.
particle/device/updates/pending
(true or false). Sent by the cloud if there is an update pending.
The event data will be the reason for the most recent reset:
Data | Description |
---|---|
unknown |
RESET_REASON_UNKNOWN |
pin_reset |
RESET_REASON_PIN_RESET |
power_management |
RESET_REASON_POWER_MANAGEMENT |
power_down |
RESET_REASON_POWER_DOWN |
power_brownout |
RESET_REASON_POWER_BROWNOUT |
watchdog |
RESET_REASON_WATCHDOG |
update |
RESET_REASON_UPDATE (firmware update) |
update_error |
RESET_REASON_UPDATE_ERROR |
update_timeout |
RESET_REASON_UPDATE_TIMEOUT |
factory_reset |
RESET_REASON_FACTORY_RESET |
safe_mode |
RESET_REASON_SAFE_MODE |
dfu_mode |
RESET_REASON_DFU_MODE |
panic |
RESET_REASON_PANIC |
user |
RESET_REASON_USER |
config_update |
RESET_REASON_CONFIG_UPDATE |
If the reason is RESET_REASON_PANIC
, then a comma and either a known panic code a number will be present:
Data | Description |
---|---|
hard_fault |
HardFault (1) |
2 |
NMIFault (2) |
memory_fault |
MemManage (3) |
bus_fault |
BusFault (4) |
usage_fault |
UsageFault (5) |
6 |
InvalidLenth (6) |
7 |
Exit (7) |
out_of_heap |
OutOfHeap (8) |
9 |
SPIOverRun (9) |
assert_failed |
AssertionFailure (10) |
10 |
AssertionFailure (10) |
11 |
InvalidCase (11) |
12 |
PureVirtualCall (12) |
stack_overflow |
StackOverflow (13) |
14 | HeapError (14) |
For example: panic, hard_fault
.
These events are planned, but not yet available.
If an update is available from the cloud, but isn't sent automatically, the cloud may publish an "flash/available" event to let the firmware know it can ask to have the update delivered.
# spark/flash/available
{ reserved / not yet implemented}
If the cloud detects than an update is very large, or the update is taking a very long time, it might decide to publish periodic flash progress events. These are meant to help you track the progress of a slow update.
# spark/flash/progress, sent,total,seconds
{ reserved / not yet implemented }
Webhooks are a powerful way to connect events from your devices to other services online.
When the webhook detects your event, it'll publish back a hook-sent event to let you know it's processing the event and has sent a request to your server.
# hook-sent
{"name":"hook-sent/your_published_event_topic","data":"undefined","ttl":"60","published_at":"2016-02-09T14:42:19.876Z","coreid":"particle-internal"}
If the hook got an error back from your server, it'll publish a hook-error event with the contents of the error.
# hook-error
{"name":"hook-error/your_published_event_topic/0","data":"Message ...","ttl":"60","published_at":"2016-02-09T15:23:23.047Z","coreid":"particle-internal"}
If the hook got a good response back, it'll break the response into 512 byte chunks and publish up to the first 100KB of the response back to your devices.
# hook-response
{"name":"hook-response/your_published_event_topic/0","data":"your server response...","ttl":"60","published_at":"2016-02-09T15:23:23.047Z","coreid":"particle-internal"}
A response larger than 512 bytes will be split into multiple parts of 512 bytes. The events are of the form:
All parts except the last will be exactly 512 bytes.
The parts may arrive out of order. This has always been the case if retransmission occurred, but as of late 2020, it will happen regularly. The reason is that events now flow through multiple redundant servers for fault tolerance and performance, but this also means that events may arrive in a different order.
There is no express indication of how many parts there are. Any part less than 512 bytes is the last part, however if the data is a multiple of 512 bytes, then it will be impossible to tell. Some formats like JSON will only be parsable after all parts have been received.
Each chunk is a separate publish from the cloud point-of-view. Each chunk uses one data operation for each Particle device it is subscribed by. Furthermore, on all devices (except the Photon and P1), each chunk has a maximum of 3 retries at the CoAP level, but no further checks are done to insure delivery. These chunks are sent out rapidly, faster than the 1 second per publish limit. Thus if you have a large number of chunks, it is likely that some may not be received by the device, especially in areas with poor cellular connectivity. There is no way to get lost chunks retransmitted.
These special webhook events cannot trigger webhooks themselves to avoid the possibility of a bad webhook recursively triggering other webhooks. Use the Console event logs or open an event stream to see these events.
Prior to March 2023, webhook events like hook-sent, hook-error, and hook-response only went to the device owner's event stream. If the device was unclaimed, the events disappeared.
Now, these events also appear in the product event stream, in the console, SSE event stream, and webhooks.
Additionally, unclaimed product devices can now subscribe to these events to get webhook responses.
A location event typically has JSON that looks like this:
{
"cmd":"loc",
"time":1584484345,
"loc":{
"lck":1,
"time":1584484333,
"lat":37.295945,
"lon":-121.986830,
"alt":71.6,
"hd":46.16,
"h_acc":10.0,
"v_acc":2.57,
"cell":37.1,
"batt":98.8
},
"trig": ["lock"],
"req_id":1
}
To estimate the data usage for location events, see this page.
This currently always the string loc
, indicating that the payload contains the loc
object.
Event time, from the device RTC. UTC time/date in 32-bit, signed, POSIX epoch format (seconds past January 1, 1970). This timestamp may be different than the timestamp in the event metadata, which is generated cloud-side when the event is received because of event queuing and retries due to connection failures.
Lock or fix status. If 0, the GNSS has not locked yet. If non-zero, it has locked and the lat/lon are valid.
GNSS timestamp. This may be different than the device and cloud times.
Latitude part of geographic coordinate in reference to WGS84 datum. It is floating point degrees in the range of -180.0 to +180.0.
Longitude part of geographic coordinate in reference to WGS84 datum. It is floating point degrees in the range of -90.0 to +90.0.
Altitude, in meters, part of geographic coordinate in reference to WGS84 datum.
Heading, in degrees, of perceived direction. It is floating point degrees in the range of -360.0 to +360.0.
Horizontal accuracy, in meters, of geographic latitude and longitude coordinates.
Vertical accuracy, in meters, of geographic altitude coordinates.
Speed, in meters per second, of perceived GNSS movement. Added in Tracker Edge v12.
Battery level, in percentage (0-100.0) when available and valid. This field will be omitted when no battery is connected.
Cellular signal strength/quality, in percentage (0-100.0).
Device temperature, in degrees Celsius, if available.
Serving and neighboring cell tower signal strength (RSSI in dBm). Added in Tracker Edge v12.
Radio Access Technology, for example, "lte". Added in Tracker Edge v12.
Mobile Country Code (0 - 999). Added in Tracker Edge v12.
Mobile Network Code (0 - 999). This is the operator or carrier within the country. Added in Tracker Edge v12.
Location Area Code (0 - 65535). Added in Tracker Edge v12.
Cell Identifier (0 - 268435455). Added in Tracker Edge v12.
Neighboring tower Physical Cell ID (0 - 2147483647). Added in Tracker Edge v12.
Frequency channel number (0 - 2147483647). Added in Tracker Edge v12.
MAC address (BSSID) for the base station (access point). Added in Tracker Edge v12.
Signal strength (RSSI in dBm). Added in Tracker Edge v12.
Wi-Fi channel number. Added in Tracker Edge v12.
Reason for point location publish message, an array of cause enumeration strings:
time
time-based (interval_max
)radius
movement-based (radius
)imu_m
IMU wake on motionimu_g
IMU wake on high-G acceleration (4g for at least 2.5ms.)temp_h
High temperature waketemp_l
Low temperature wakeuser
User-triggered publishbatt_warn
Low battery warningbatt_low
Low batteryoutside1
The device is currently outside of geofence zone 1 (and outside trigger is enabled)inside1
The device is currently inside of geofence zone 1 (and inside trigger is enabled)enter1
The device has entered geofence zone 1 (and enter trigger is enabled)exit1
The device has exited geofence zone 1 (and exit trigger is enabled)outside2
, inside2
, enter2
, and exit2
outside3
, inside3
, enter3
, and exit3
outside4
, inside4
, enter4
, and exit4
The request identifier, used to make sure the event was received.
The loc-enhanced
event includes Location Fusion information, enhanced geolocation using Wi-Fi and/or cellular tower information. This can occur indoors, and in "urban canyons" where view of the GNSS satellites is obstructed.
loc-enhanced
events are generated by the Particle cloud, one for every loc
event sent by the Tracker, with any additional location information added. The enhanced location can be monitored using webhooks or server-sent-events. Optionally, these events can also be sent to devices, to allow the device to act on the enhanced location information. See location configuration.
The loc-enhanced
event will have data the same as the original loc
event, such as: cmd
, time
, loc.lck
, loc.cell
, loc.batt
, loc.temp
, loc.time
, loc.lat
, loc.lon
, loc.h_acc
, and trig
.
Note that loc.alt
(altitude), loc.v_acc
(vertical accuracy), loc.hd
(heading), and loc.spd
(speed) are not available for locations derived from location fusion, but if that information was in the original loc
event from the GNSS, it will be preserved in the loc-enhanced
event.
The sources used for enhanced geolocation, an array. Can be "cell" or "wifi" or both. Added in Tracker Edge v12.
The full JSON schema for the location point can be downloaded here.
PUT /v1/devices/:deviceId
Update the device firmware from source
Device ID
The source code encoded in multipart/form-data
format
The firmware version to compile against. Defaults to latest
$ curl -X PUT https://api.particle.io/v1/devices/0123456789abcdef01234567 \
-F "file=@application.cpp;filename=application.cpp" \
-F "file1=@lib/my_lib.cpp;filename=lib/my_lib.cpp" \
-F "file2=@lib/my_lib.h;filename=lib/my_lib.h" \
-H "Authorization: Bearer :access_token"
PUT /v1/devices/0123456789abcdef01234567
HTTP/1.1 200 OK
{
"ok": true,
"message": "Update started"
}
PUT /v1/devices/:deviceId
Update the device firmware from a binary
Device ID
The pre-compiled binary encoded in multipart/form-data
format.
$ curl -X PUT https://api.particle.io/v1/devices/0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token" \
-F file=@my-firmware-app.bin
PUT /v1/devices/0123456789abcdef01234567
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"status": "Update started"
}
PUT /v1/devices/:deviceId
Update the device firmware from a bundle
Device ID
The bundle encoded in multipart/form-data
format. The MIME type must be application/zip
.
$ curl -X PUT https://api.particle.io/v1/devices/0123456789abcdef01234567 \
-H "Authorization: Bearer :access_token" \
-F "file=@my-firmware-bundle.zip;type=application/zip"
PUT /v1/devices/0123456789abcdef01234567
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"status": "Update started"
}
POST /v1/binaries
Compile source code into a binary for a device
The source code encoded in multipart/form-data
format
The platform ID to target the compilation
The product to target for compilation
The firmware version to compile against. Defaults to latest
$ curl -X POST https://api.particle.io/v1/binaries \
-F platform_id=6 \
-F "file=@application.cpp;filename=application.cpp" \
-F "file1=@lib/my_lib.cpp;filename=lib/my_lib.cpp" \
-F "file2=@lib/my_lib.h;filename=lib/my_lib.h" \
-H "Authorization: Bearer :access_token"
POST /v1/binaries
HTTP/1.1 200 OK
{
"ok": true,
"binary_id": "5734a5d4a71c2601243809e6",
"binary_url": "/v1/binaries/5734a5d4a71c2601243809e6",
"build_target_version": "1.5.1",
"expires_at": "2016-05-13T15:48:27.997Z",
"sizeInfo": " text\t data\t bss\t dec\t hex\tfilename\n 91780\t 952\t 9368\t 102100\t 18ed4\t"
}
GET /v1/build_targets
Lists the firmware versions for all platforms that can be used as build targets during firmware compilation.
Note: This endpoint does not require an access token.
When true, show most relevant (featured) build targets only.
$ curl https://api.particle.io/v1/build_targets
Array of build target objects
Name of each platform ID with a build target
PUT /v1/build_targets
HTTP/1.1 200 OK
{
"targets": [
{
"platforms": [
0,
10,
8,
6
],
"prereleases": [],
"firmware_vendor": "Particle",
"version": "0.6.1"
}
],
"platforms": {
"Core": 0,
"Photon": 6,
"P1": 8,
"Electron": 10
},
"default_versions": {
"0": "0.7.0",
"6": "2.3.1",
"8": "2.3.1",
"10": "2.3.1"
}
}
As of April, 2023, an access token is no longer required to call this API.
PUT /v1/products/:productIdOrSlug/devices/:deviceId
Locks a product device to a specific version of product firmware. This device will download and run this firmware if it is not already running it the next time it connects to the cloud. You can optionally trigger an immediate update to this firmware for devices that are currently online
devices:update
Device ID
Product ID or slug. Product endpoint only
The firmware version the device should be locked to
Set to true
to immediately flash to a device. Will only successfully deliver the firmware update if the device is currently online and connected to the cloud.
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/12345 \
-d desired_firmware_version=1 \
-d flash=true \
-H "Authorization: Bearer :access_token"
Device ID
The newly set firmware version to lock the device to
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/products/:productIdOrSlug/devices/12345
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"desired_firmware_version": 1,
"updated_at": "2017-03-10T20:21:49.059Z"
}
PUT /v1/products/:productIdOrSlug/devices/:deviceId
Unlocks a product device from receiving and running a specific version of product firmware. The device will now be eligible to receive released firmware in the product.
devices:update
Device ID
Product ID or slug. Product endpoint only
Set to null
to unlock the device
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/12345 \
-d desired_firmware_version=null \
-H "Authorization: Bearer :access_token"
Device ID
Should now be null
signaling that the device is no longer locked to a specific version of firmware
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/products/:productIdOrSlug/devices/12345
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"desired_firmware_version": null
"updated_at": "2017-03-10T20:21:49.059Z"
}
PUT /v1/products/:productIdOrSlug/devices/:deviceId
Mark a device in a product fleet as a development device. Once marked as a development device, it will opt-out from receiving automatic product firmware updates. This includes both locked firmware as well as released firmware.
devices:update
Device ID
Product ID or slug
Set to true
to mark as development device
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/12345 \
-d development=true \
-H "Authorization: Bearer :access_token"
Device ID
Should now be true
signaling that the device is now a development device
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/products/:productIdOrSlug/devices/12345
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"development": true
"updated_at": "2017-03-10T20:21:49.059Z"
}
PUT /v1/products/:productIdOrSlug/devices/:deviceId
Unmark a device in a product fleet as a development device. Once unmarked, the device will opt-in to receiving automatic product firmware updates. This includes both locked firmware as well as released firmware.
devices:update
Device ID
Product ID or slug
Set to false
to unmark as development device
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/12345 \
-d development=false \
-H "Authorization: Bearer :access_token"
Device ID
Should now be false
signaling that the device is not a development device
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/products/:productIdOrSlug/devices/12345
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"development": false
"updated_at": "2017-03-10T20:21:49.059Z"
}
While compiling source code using the cloud compiler, or flashing a device with source code, there are limits:
This affects the following endpoints:
POST /v1/binaries
PUT /v1/devices/:deviceId
GET /v1/products/:productIdOrSlug/firmware/:version
Get a specific version of product firmware
firmware:get
Product ID or slug
Version number of firmware to retrieve
$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware/1 \
-H "Authorization: Bearer :access_token"
The ID of the firmware
The version number of the firmware
The title of the firmware
A description of the firmware
The firmware's file name
The size of the firmware in bytes
Whether the firmware is released as the product default
An array of group names representing the groups the firmware version has been released to
[Enterprise only] Product upgrades and downgrades apply this version of firmware before flashing the targeted version.
Timestamp of when the firmware was uploaded
The ID of the product that owns the firmware
The user who uploaded the firmware
GET /v1/products/:productIdOrSlug/firmware/1
HTTP/1.1 200 OK
{
"_id":"58c09bc7df2b9a4d223d9c22",
"version":1,
"title":"My Firmware",
"description":"Sample firmware description",
"name":"firmware.bin",
"size":7952,
"product_default":false,
"uploaded_on":"2017-03-09T00:03:19.181Z",
"product_id":295,
"mandatory":false,
"uploaded_by":{
"username":"jeff@particle.io",
...
}
}
GET /v1/products/:productIdOrSlug/firmware
List all versions of product firmware
firmware:list
Product ID or slug
$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware \
-H "Authorization: Bearer :access_token"
An array of product firmware objects. See above for details on the firmware object.
GET /v1/products/:productIdOrSlug/firmware
HTTP/1.1 200 OK
[
{
"_id":"58c09bc7df2b9a4d223d9c22",
"version":1,
"title":"My Firmware",
"description":"Sample firmware description",
"name":"firmware.bin",
"size":7952,
"product_default":false,
"uploaded_on":"2017-03-09T00:03:19.181Z",
"product_id":295,
"uploaded_by":{
"username":"jeff@particle.io",
},
"groups":{
["asia","europe","america"],
},
"device_count":200
},
...
]
POST /v1/products/:productIdOrSlug/firmware
Upload a new firmware version to a product
firmware:create
Product ID or slug
The version number of the firmware binary you are uploading
Title of the firmware version. Handy for quickly identifying the firmware
A binary file encoded in multipart/form-data
format containing the contents of the product firmware (binary
is also accepted for backwards compatibility). When uploading a bundle, the MIME type must be application/zip
Product ID or slug
Optionally provide a description for the new firmware version
[Enterprise only] Flag this firmware release as a mandatory release so that product upgrades and downgrades apply this version of firmware before flashing the targeted version.
$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware \
-H "Authorization: Bearer :access_token" \
-F file=@firmware.bin \
-F version=1 \
-F title=firmware
$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware \
-H "Authorization: Bearer :access_token"
-F "file=@bundle.zip;type=application/zip" \
-F version=1 \
-F title=firmware
The newly created firmware object. See above for details on the firmware object.
POST /v1/products/:productIdOrSlug/firmware
HTTP/1.1 201 Created
{
"_id":"58c09bc7df2b9a4d223d9c22",
"version":1,
"title":"My Firmware",
"description":"Sample firmware description",
"name":"firmware.bin",
"size":7952,
"current":false
"uploaded_on":"2017-03-09T00:03:19.181Z",
"product_id":295,
"uploaded_by":{
"username":"jeff@particle.io",
...
}
}
PUT /v1/products/:productIdOrSlug/firmware/:version
Edit a specific product firmware version
firmware:update
Product ID or slug
Version number of the firmware to edit
Provide a new title for the firmware
Provide a new description for the firmware
[Enterprise only] Flag this firmware release as a mandatory release so that product upgrades and downgrades apply this version of firmware before flashing the targeted version.
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/firmware/1 \
-d title="New title" \
-d description="New description" \
-H "Authorization: Bearer :access_token"
The updated firmware object. See above for details on the firmware object.
PUT /v1/products/:productIdOrSlug/firmware/1
HTTP/1.1 200 OK
{
"_id":"58c09bc7df2b9a4d223d9c22",
"version":1,
"title":"New title",
"description":"New description",
"name":"firmware.bin",
"size":7952,
"current":false
"uploaded_on":"2017-03-09T00:03:19.181Z",
"product_id":295,
"uploaded_by":{
"username":"jeff@particle.io",
...
}
}
GET /v1/products/:productIdOrSlug/firmware/:version/binary
Retrieve and download the original binary of a version of product firmware.
firmware.binary:get
Product ID or slug
Version number of firmware to retrieve
$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware/1/binary \
-H "Authorization: Bearer :access_token"
The binary file of the requested product firmware version
PUT /v1/products/:productIdOrSlug/firmware/release
Release a version of firmware to the fleet of product devices. When releasing as the product default, all non-development devices that are not individually locked to a version of product firmware will automatically download and run this version of firmware the next time they handshake with the cloud.
You can also release firmware to specific groups for more fine-grained firmware management.
Note: Before releasing firmware for the first time, the firmware must be running on at least one device in your product fleet that has successfully re-connected to the Particle cloud.
firmware:release
Product ID or slug
firmware version number to release to the fleet
Pass true
to set the firmware version as the product default release
An array of device groups to release the firmware to.
Flag this firmware release as an intelligent release so that devices do not need to reconnect to the cloud to receive the update and that they are informed of pending updates when devices are not available for updating.
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/firmware/release \
-d version=1 \
-d groups[]="foo&groups[]=bar&groups[]=baz"
-H "Authorization: Bearer :access_token"
The released firmware object. See above for details on the firmware object.
PUT /v1/products/:productIdOrSlug/firmware/release
HTTP/1.1 200 OK
{
"updated_at": "2017-07-20T23:53:15.298Z",
"version":1,
"title":"New title",
"size":7952,
"product_default":false,
"uploaded_on":"2017-03-09T00:03:19.181Z",
"product_id":295,
"uploaded_by":{
"username":"jeff@particle.io",
},
"groups": ["foo", "bar", "baz"],
"intelligent": true
}
DELETE /v1/products/:productIdOrSlug/firmware/:version
Delete a version of product firmware that has never been released.
firmware:remove
Product ID or slug
Version number of firmware to delete
$ curl -X DELETE https://api.particle.io/v1/products/:productIdOrSlug/firmware/1 \
-H "Authorization: Bearer :access_token"
DELETE /v1/products/:productIdOrSlug/firmware/1
HTTP/1.1 204 No Content
The libraries endpoints are a little different as they follow the JSON API specification.
GET /v1/libraries
List firmware libraries. This includes private libraries visibile only to the user.
Search for libraries with this partial name
Page number
Items per page (max 100)
Sort order for results. Prefix with -
for descending order.
name
installs
popularity
published
updated
created
official
verified
Which subset of libraries to list.
all
to retrieve public libraries and any private libraries belonging to the userofficial
to retrieve official public librariespublic
to retrieve public librariesmine
to retrieve only public libraries belonging to the current userprivate
to retrieve only private libraries (belonging to the current user).Which subsets of libraries to avoid listing, separated by comma. Same values as scope
.
Architectures to list, separated by comma. Missing means all architectures.
$ curl "https://api.particle.io/v1/libraries?scope=official&sort=name" \
-H "Authorization: Bearer :access_token"
Array of library objects. Described in Get library details
GET /v1/libraries?limit=2
HTTP/1.1 200 OK
{
"data": [
{
"type": "libraries",
"id": "neopixel",
"links": {
"download": "https://library-archives.particle.io/libraries/neopixel/neopixel-0.0.10.tar.gz"
},
"attributes": {
"name": "neopixel",
"version": "0.0.10",
"installs": 9125,
"license": "GNU GPLv3",
"author": "Adafruit, Technobly",
"sentence": "An Implementation of Adafruit's NeoPixel Library for the Spark Core, Particle Photon, P1, Electron and RedBear Duo",
"url": "https://github.com/technobly/sparkcore-neopixel",
"repository": "https://github.com/technobly/sparkcore-neopixel.git",
"architectures": [],
"visibility": "public",
"official": true,
"mine": false,
"verified": true
}
},
{
"type": "libraries",
"id": "InternetButton",
"links": {
"download": "https://library-archives.particle.io/libraries/InternetButton/InternetButton-0.1.10.tar.gz"
},
"attributes": {
"name": "InternetButton",
"version": "0.1.10",
"installs": 7660,
"license": "LGPL",
"author": "Richard Whitney ",
"sentence": "Functions to make the Internet Button easy to use! If you have an original SparkButton, make sure to use `begin(1)`",
"url": "https://github.com/spark/internetbutton",
"repository": "https://github.com/spark/internetbutton.git",
"architectures": [],
"visibility": "public",
"official": true,
"mine": false
}
}
]
}
GET /v1/libraries/:libraryName
Get details for a firmware library.
Name of library to retrieve (case insensitive)
Version to retrieve. Defaults to the latest version.
Which subset of versions to get.
all
public
private
$ curl https://api.particle.io/v1/libraries/internetbutton \
-H "Authorization: Bearer :access_token"
The library version in JSON API format
The name of the library
The URL to download the files for this library
Additional meta data for the library. Not all fields are available for every library.
GET /v1/libraries/internetbutton
HTTP/1.1 200 OK
{
"data": {
"type": "libraries",
"id": "InternetButton",
"links": {
"download": "https://library-archives.particle.io/libraries/InternetButton/InternetButton-0.1.10.tar.gz"
},
"attributes": {
"name": "InternetButton",
"version": "0.1.10",
"installs": 7660,
"license": "LGPL",
"author": "Richard Whitney richard@particle.io",
"sentence": "Functions to make the Internet Button easy to use! If you have an original SparkButton, make sure to use begin(1)
",
"url": "https://github.com/spark/internetbutton",
"repository": "https://github.com/spark/internetbutton.git",
"architectures": [],
"visibility": "public",
"official": true,
"mine": false
}
}
}
GET /v1/libraries/:libraryName/versions
Get details for all versions of a firmware library.
Name of library to retrieve (case insensitive)
Which subset of versions to get.
all
public
private
$ curl https://api.particle.io/v1/libraries/internetbutton\versions \
-H "Authorization: Bearer :access_token"
Array of library version objects. Described in Get library details
GET /v1/libraries/internetbutton/versions
HTTP/1.1 200 OK
{
"data": [
{
"type": "libraries",
"id": "InternetButton",
"links": {
"download": "https://library-archives.particle.io/libraries/InternetButton/InternetButton-0.1.9.tar.gz"
},
"attributes": {
"name": "InternetButton",
"version": "0.1.9",
"installs": 7660,
"license": "LGPL",
"author": "Richard Whitney richard@particle.io",
"sentence": "Functions to make the Internet Button easy to use! If you have an original SparkButton, make sure to use begin(1)
",
"url": "https://github.com/spark/internetbutton",
"repository": "https://github.com/spark/internetbutton.git",
"architectures": [],
"visibility": "public",
"official": true,
"mine": false
}
},
{
"type": "libraries",
"id": "InternetButton",
"links": {
"download": "https://library-archives.particle.io/libraries/InternetButton/InternetButton-0.1.10.tar.gz"
},
"attributes": {
"name": "InternetButton",
"version": "0.1.10",
"installs": 7660,
"license": "LGPL",
"author": "Richard Whitney richard@particle.io",
"sentence": "Functions to make the Internet Button easy to use! If you have an original SparkButton, make sure to use begin(1)
",
"url": "https://github.com/spark/internetbutton",
"repository": "https://github.com/spark/internetbutton.git",
"architectures": [],
"visibility": "public",
"official": true,
"mine": false
}
}
]
}
POST /v1/libraries/:libraryName
Upload a private version of a firmware library. If the library doesn't exist it is created.
The library will be validated and an error response returned if invalid.
Name of library to retrieve (case insensitive)
A tar-gzip archive of all the files for the library.
The meta data like name and version is taken from library.properties.
See
the example library for other files to include.
$ curl https://api.particle.io/v1/libraries \
-F "archive=@library.tar.gz" \
-H "Authorization: Bearer :access_token"
The library version created. Described in Get library details
POST /v1/libraries
HTTP/1.1 201 Created
{
"data": {
"type": "libraries",
"id": "testlib43",
"links": {
"download": "https://library-archives.particle.io/libraries/testlib43/testlib43-1.0.2.tar.gz"
},
"attributes": {
"name": "testlib43",
"version": "1.0.2",
"license": "MIT",
"author": "JV",
"sentence": "one sentence description of this library",
"url": "the URL of the project, like https://github.com/mygithub_user/my_repo",
"repository": "mygithub_user/my_repo",
"architectures": [],
"visibility": "private"
}
}
}
POST /v1/libraries
HTTP/1.1 400 Bad Request
{
"errors": [
{
"message": "This version is not valid. Version must be greater than or equal to 1.0.2"
}
]
}
PATCH /v1/libraries/:libraryName
Make the latest private version of a firmware library public. You must do this before others can access your uploaded library.
Name of library to retrieve (case insensitive)
Must be set to public
to publish a library.
$ curl -X PATCH https://api.particle.io/v1/libraries/testlib43 \
-d "visibility=public" \
-H "Authorization: Bearer :access_token"
The library version published. Described in Get library details
PATCH /v1/libraries/testlib43
HTTP/1.1 200 OK
{
"data": {
"type": "libraries",
"id": "testlib43",
"links": {
"download": "https://library-archives.particle.io/libraries/testlib43/testlib43-1.0.2.tar.gz"
},
"attributes": {
"name": "testlib43",
"version": "1.0.2",
"license": "MIT",
"author": "JV",
"sentence": "one sentence description of this library",
"url": "the URL of the project, like https://github.com/mygithub_user/my_repo",
"repository": "mygithub_user/my_repo",
"architectures": [],
"visibility": "public"
}
}
}
GET /v1/user/products
List products the currently authenticated user has access to
products:list
$ curl https://api.particle.io/v1/user/products \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/orgs/particle/products \
-H "Authorization: Bearer :access_token"
List of Products
GET /v1/user/products
HTTP/1.1 200 OK
{
"products": [{
"id": 12345,
"platform_id": 10,
"name": "My Product",
"slug": "my-product",
"description": "My test product",
"subscription_id": 1234,
"user": "me@example.com"
"groups": [
"one",
"two"
],
"settings": {
"location": {},
"known_application": {
"opt_in": true
},
"quarantine": false
}
}]
}
GET /v1/products/:productIdOrSlug
Retrieve details for a product.
products:get
Product ID or Slug
Product Unique ID
Product Firmware ID
Product Name
URL compatible version of name
Product Platform ID
Organization Unique ID
The set device protection status of the devices in this product
GET /v1/products/photon
HTTP/1.1 200 OK
{
"product": {
"id": 12345,
"platform_id": 10,
"name": "My Product",
"slug": "my-product",
"description": "My test product",
"subscription_id": 1234,
"user": "me@example.com"
"groups": [
"one",
"two"
],
"settings": {
"location": {},
"known_application": {
"opt_in": true
},
"quarantine": false
},
"device_protection": "disabled"
}
}
GET /v1/products/:productIdOrSlug/team
List all team members that are part of a given product. Also, will retrieve all API users for all the products inside the org
teams.users:list
Product ID or slug
$ curl https://api.particle.io/v1/products/:productIdOrSlug/team \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/orgs/:orgIdOrSlug/team \
-H "Authorization: Bearer :access_token"
An array of team members
ID of the team member
Username of the team member
GET /v1/products/:productIdOrSlug/team
HTTP/1.1 200 OK
{
"ok": true.
"team": [
{
"_id":"9980222caf8bad191600019b",
"username":"jeff@particle.io",
"no_mfa": true,
"scim_provisioned": true,
"no_password": true
},
{
"username": "test-product-api-user+abc1234@api.particle.io",
"friendly_name": "test-product-api-user",
"scopes": [ "products:list" ],
"is_programmatic": true,
"product_id": 123456
},
...
]
}
POST /v1/products/:productIdOrSlug/team
Invite a new member to a product team. Invitee will receive an email with a link to accept the invitation and join the team.
teams.users:invite
teams.users:invite
Product ID or Slug
Username of the invitee. Must be a valid email associated with an Particle user
The role for the invited user. One of Administrator, Developer, View-only, Support.
$ curl "https://api.particle.io/products/:productIdOrSlug/team" \
-d username=test@example.com \
-d role=Administrator \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/orgs/:orgIdOrSlug/team" \
-d username=test@example.com \
-d role=Administrator \
-H "Authorization: Bearer :access_token"
The invited user
POST /v1/products/:productIdOrSlug/team
HTTP/1.1 200 OK
{
"ok": true,
"invited": {
"username": "test@example.com"
}
}
POST /v1/products/:productIdOrSlug/team
Create an API user with specified scopes. This API user will have a single non-expiring access token.
teams.users:invite
Product ID or Slug
A friendly name used to recognise the user
List of scopes to grant for this user
$ curl https://api.particle.io/products/:productIdOrSlug/team \
-H "Authorization: Bearer :access_token"
-H "Content-Type: application/json" \
-d '{
"friendly_name": "MyToken",
"scopes: ["foo:bar"]
}'
The created API user
POST /v1/products/:productIdOrSlug/team
HTTP/1.1 200 OK
{
"ok": true,
"created": {
"username": "mytoken+sdfdsfdse34@api.particle.io",
"is_programmatic": true,
"tokens": [
"token": "abc123"
]
}
}
POST /v1/products/:productIdOrSlug/team/:username
Update a current team member.
teams.users:update
Product ID or Slug
Username of the team member to be updated
DELETE /v1/products/:productIdOrSlug/team/:username
Remove a current team member.
teams.users:remove
Product ID or Slug
Username of the team member to be removed
$ curl -X DELETE https://api.particle.io/products/:productIdOrSlug/team/test@example.com \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE https://api.particle.io/orgs/:orgIdOrSlug/team/test@example.com \
-H "Authorization: Bearer :access_token"
DELETE /v1/products/photon/team/jeff@particle.io
HTTP/1.1 200 OK
{
"ok": true
}
PUT /v1/products/:productIdOrSlug/team/:username/token
Regenerate programmatic users token
teams.users:update
Product ID or Slug
Username of the team member to be updated
$ curl -X POST https://api.particle.io/products/:productIdOrSlug/team/test+prg123@example.com/token \
-H "Authorization: Bearer :access_token"
$ curl -X POST https://api.particle.io/orgs/:orgIdOrSlug/team/test+prg123@example.com/token \
-H "Authorization: Bearer :access_token"
POST /v1/products/photon/team/test+prg123@example.com/team
HTTP/1.1 200 OK
{
"ok": true,
"updated":{
"username": "test+prg123@example.com",
"tokens": [
{
"token": "abc.123"
}
]
}
}
Device groups allow you to define subsets of your IoT deployment that can be addressed separately from the rest of the fleet. Groups are defined within the scope of a product. For more information, please see the guide.
GET /v1/products/:productIdOrSlug/groups/:groupName
Retrieve full info on a specific product group, including its device count.
groups:get
Product ID or slug
The group name to fetch
$ curl https://api.particle.io/v1/products/:productIdOrSlug/groups/group_a \
-H "Authorization: Bearer :access_token"
The group object
The name of the group
A description of the group
A hex value representing of the color displayed next to the group tag on the Console
The version number of the product firmware that has been released to this group
The number of devices that belong to this group
GET /v1/products/:productIdOrSlug/groups/group_a
HTTP/1.1 200 OK
{
"group": {
"name":"group_a",
"description":"first group A",
"color":"#e74c3c",
"fw_version":1,
"device_count":3
}
}
GET /v1/products/:productIdOrSlug/groups
List the group objects that exist in the product. Optionally, filter by group name (partial match).
groups:list
Product ID or slug
String to filter group names by. Partial string matching.
$ curl "https://api.particle.io/v1/products/:productIdOrSlug/groups?name=gr" \
-H "Authorization: Bearer :access_token"
An array of the device groups objects
GET /v1/products/:productIdOrSlug/groups?name=gr
HTTP/1.1 200 OK
{
"groups": [
{
"name":"group_a",
"description":"the A group",
"fw_version":3,
"color":"#34495e"
},
{
"name":"group_b",
"description": "the B group",
"color":"#34495e"
}
]
}
POST /v1/products/:productIdOrSlug/groups
Create a new device group withinin a product
groups:create
Product ID or slug
The name of the group. Must only contain lowercase letters, numbers, dashes, and underscores.
A hex value representing of the color displayed next to the group tag on the Console
String A description of the group
$ curl https://api.particle.io/v1/products/:productIdOrSlug/groups \
-d name=group_a \
-d description="the A group" \
-d color="#34495e" \
-H "Authorization: Bearer :access_token"
The group object
POST /v1/products/:productIdOrSlug/groups
HTTP/1.1 201 Created
{
"group": {
"name": "group_a",
"description": "the A group",
"color": "#34495e"
}
}
PUT /v1/products/:productIdOrSlug/groups/:groupName
Edit attributes of a specific device group. You must pass one of name
, color
, or description
.
groups:update
Product ID or slug
The group name to edit
Provide a new group name
Provide a new group color
Provide a new description
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/groups/group_a \
-d name=double_agent \
-H "Authorization: Bearer :access_token"
The updated group object
PUT /v1/products/:productIdOrSlug/groups/group_a
HTTP/1.1 200 OK
{
"group": {
"name":"double_agent",
"description":"group description",
"color":"#e74c3c",
"fw_version":1,
"device_count":3
}
}
DELETE /v1/products/:productIdOrSlug/groups/:groupName
Delete device group. All devices that belong to this group will be removed from the deleted group.
groups:remove
Product ID or slug
The group name to delete
$ curl -X DELETE https://api.particle.io/v1/products/:productIdOrSlug/groups/group_a \
-H "Authorization: Bearer :access_token"
DELETE /v1/products/:productIdOrSlug/groups/group_a
HTTP/1.1 204 NO CONTENT
PUT /v1/products/:productIdOrSlug/devices/:deviceId
Update group memberships for an individual device. This is an absolute endpoint, meaning that regardless of previous group memberships, the group names passed to this endpoint will be the ones assigned to the device.
If you pass a group name that does not yet exist, it will be created and assigned to the device.
devices:update
Device ID
Product ID or slug
Array of group names
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/12345 \
-d groups[]="testing" \
-H "Authorization: Bearer :access_token"
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices/12345 \
-d groups[]="europe&groups[]=asia" \
-H "Authorization: Bearer :access_token"
Device ID
Array of updated device group names
Timestamp representing the last time the deivce was updated in ISO8601 format
PUT /v1/products/:productIdOrSlug/devices/12345
HTTP/1.1 200 OK
{
"id": "0123456789abcdef01234567",
"groups": ["europe", "asia"]
"updated_at": "2017-03-10T20:21:49.059Z"
}
PUT /v1/products/:productIdOrSlug/devices
Assign groups to devices in a product as a batch action. Groups can either be added or removed from all devices passed to the endpoint.
devices:update
Product ID or slug
Set to groups
An array of device IDs to update group memberships
metadata object to inform which groups should be added/removed
Array of group names to add to devices
Array of group names to remove to devices
$ curl -X PUT https://api.particle.io/v1/products/:productIdOrSlug/devices \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{"action": "groups", "devices": ["123", "456"], "metadata": {"add": ["foo"]}}'
PUT /v1/products/:productIdOrSlug/devices
HTTP/1.1 200 OK
{
"ok": true
}
GET /v1/products/:productIdOrSlug/impact
Understand the number of devices that would receive an over-the-air update as a result of taking an action related to device groups.
Currently, this endpoint supports understanding the impact of releasing/unreleasing firmware to one or more device groups. Pass edit_groups_for_firmware
as the action
parameter when calling the endpoint.
groups.impact:get
Product ID or slug
The action you are about to take. Currently only accepts edit_groups_for_firmware
Firmware version you wish to release
Comma separated list of device group names to release the firmware_version
version to. Do not include to simulate the impact of unreleasing to all groups.
Set to true
if you intend to release this firmware_version
as the product default firmware. Set to false
if the firmware is currently marked as product_default
to simulate unreleasing as the product_default
.
$ curl https://api.particle.io/v1/products/:productIdOrSlug/impact?\
&action=edit_groups_for_firmware\
&groups=asia,europe\
&firmware_version=3\
&product_default=false\
-H "Authorization: Bearer :access_token"
object containing impact details
number of devices which will get OTA update resulting from the planned groups action
number of devices which will get OTA update broken out by the firmware version they'll be flashed with. Each sub-object will have the version
of product firmware and the total
number of devices that will receive this
version of firmware.
GET /v1/products/:productIdOrSlug/impact
HTTP/1.1 200 OK
{
devices: {
firmware_update: {
total: 123,
by_version: [
{
version: 1,
total: 25
},
{
...
}
]
}
}
}
GET /v1/products/:productIdOrSlug/fleet_locations
Get the latest location data for all the devices in a product to get a fleet-wide summary of device location.
locations:get
Product ID or slug.
Device ID prefix to include in the query
Device name prefix to include in the query
Array of group names to include in the query
$ curl "https://api.particle.io/v1/products/1234/fleet_locations" \
-H "Authorization: Bearer :access_token"
GET https://api.particle.io/v1/products/1234/fleet_locations
HTTP/1.1 200 OK
{
"locations": [{
"device_id": "1234567890abcdef",
"product_id": 343,
"device_name" : "deploy-truck32",
"gps_lock": true,
"last_heard": "2020-12-07T21:07:12Z",
"groups": ["us-east", "trucks"],
"timestamps": [
"2020-12-07T21:07:12Z",
],
"geometry": {
"type": "Point",
"coordinates": [
34.518699645996094,
31.504855323809403
]
}
}, {
"device_id": "deadbeef123456",
"product_id": 343,
"groups": ["us-east"],
"device_name": "service-truck11",
"timestamp": "2020-12-07T21:07:12Z",
"gps_lock": true,
"last_heard": "2020-12-07T21:07:12Z",
"geometry": {
"type": "Point",
"coordinates": [
33.548699645996094,
30.804855323809403
]
},
}]
}
GET /v1/products/:productIdOrSlug/locations
Get latest or historical location data for devices. Date range and bounding box can be specified to narrow the query.
locations:get
Product ID or slug.
Start and end date in ISO8601 format, separated by comma, to query. Omitting date_range will return last known location.
Bottom left of the rectangular bounding box to query. Latitude and longitude separated by comma.
Top right of the rectangular bounding box to query. Latitude and longitude separated by comma.
Device ID prefix to include in the query
Device name prefix to include in the query
Array of group names to include in the query
Page of results to display. Defaults to 1
Number of results per page. Defaults to 20. Maximum of 100
$ curl "https://api.particle.io/v1/products/1234/locations?rect_bl=30.5,30.0&rect_tr=36.2,35.6&date_range=2020-12-05T20:00:00Z,2020-12-05T20:07:39Z&device_name=service-truck" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/products/1234/locations?rect_bl=30.5,30.0&rect_tr=36.2,35.6" \
-H "Authorization: Bearer :access_token"
GET https://api.particle.io/v1/products/1234/locations
HTTP/1.1 200 OK
{
"locations": [{
"device_id": "1234567890abcdef",
"product_id": 343,
"device_name" : "service-truck7",
"groups": ["us-east", "trucks"],
"gps_lock": true,
"last_heard": "2020-12-05T20:06:12Z",
"timestamps": [
"2020-12-05T20:03:40Z",
"2020-12-05T20:04:23Z",
"2020-12-05T20:05:44Z",
"2020-12-05T20:06:12Z",
],
"online": false,
"geometry": {
"type": "LineString",
"coordinates": [[
34.518699645996094,
31.504855323809403
],[
34.528699645996094,
31.604855323809403
],[
34.538699645996094,
31.704855323809403
],[
34.548699645996094,
31.804855323809403
]]
}
}, {
"device_id": "deadbeef123456",
"product_id": 343,
"device_name": "service-truck11",
"groups": ["us-east"],
"gps_lock": true,
"last_heard": "2020-12-05T20:06:12Z",
"timestamps": [
"2020-12-05T20:04:23Z",
"2020-12-05T20:05:44Z",
"2020-12-05T20:06:12Z",
],
"online": true,
"geometry": {
"type": "LineString",
"coordinates": [[
33.518699645996094,
30.504855323809403
], [
33.528699645996094,
30.604855323809403
], [
33.538699645996094,
30.704855323809403
]]
},
}],
"meta": {
"page" : 1,
"per_page" : 20,
"total_pages" : 5,
"devices_found" : 100,
}
}
GET https://api.particle.io/v1/products/1234/locations
HTTP/1.1 200 OK
{
"locations": [{
"device_id": "1234567890abcdef",
"product_id": 343,
"device_name" : "deploy-truck32",
"gps_lock": true,
"last_heard": "2020-12-07T21:07:12Z",
"groups": ["us-east", "trucks"],
"timestamps": [
"2020-12-07T21:07:12Z",
],
"geometry": {
"type": "Point",
"coordinates": [
34.518699645996094,
31.504855323809403
]
}
}, {
"device_id": "deadbeef123456",
"product_id": 343,
"groups": ["us-east"],
"device_name": "service-truck11",
"timestamp": "2020-12-07T21:07:12Z",
"gps_lock": true,
"last_heard": "2020-12-07T21:07:12Z",
"geometry": {
"type": "Point",
"coordinates": [
33.548699645996094,
30.804855323809403
]
},
}],
"meta": {
"page" : 1,
"total_pages" : 1,
"per_page" : 20,
"devices_found" : 2,
}
}
GET /v1/products/:productIdOrSlug/locations/:deviceId
Get last known or historical location data for one device. Date range and bounding box can be specified to narrow down the query. Properties and custom data will be returned by default.
locations:get
Product ID or slug.
Device ID
Start and end date in ISO8601 format, separated by comma, to query. Omitting date_range will return last known location.
Bottom left of the rectangular bounding box to query. Latitude and longitude separated by comma.
Top right of the rectangular bounding box to query. Latitude and longitude separated by comma.
$ curl "https://api.particle.io/v1/products/1234/locations/123456?rect_bl=10.5,11&rect_tr=11.0,11.5&date_range=2020-12-05T20:00:00Z,2020-12-05T20:07:39Z" \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/products/1234/locations/123456 \
-H "Authorization: Bearer :access_token"
GET https://api.particle.io/v1/products/1234/locations/123456
HTTP/1.1 200 OK
{
"location": {
"device_id": "1234567890abcdef",
"device_name" : "ice-cream-truck3",
"product_id": 343,
"gps_lock" : true,
"last_heard" : "2020-12-05T20:06:120Z",
"groups": ["us-east", "truck"],
"timestamps": [
"2020-12-05T20:03:40Z",
"2020-12-05T20:04:23Z",
"2020-12-05T20:05:44Z",
"2020-12-05T20:06:120Z"
],
"online": true,
"geometry": {
"type": "LineString",
"coordinates": [[
34.518699645996094,
31.504855323809403
],[
34.528699645996094,
31.604855323809403
],[
34.538699645996094,
31.704855323809403
],[
34.548699645996094,
31.804855323809403
]]
},
"properties": [{
"hd" : 36.6,
"acc_h": 5.0,
"speed": 13.5,
"temp": 77.4
},{
"hd" : 37.6,
"acc_h": 6.0,
"speed": 13.5,
"temp": 69.4
},{
"hd" : 41.6,
"acc_h": 11.8,
"speed": 16.5,
"temp": 75.4
},{
"hd" : 42.6,
"acc_h": 7.9,
"speed": 15.5,
"temp": 78.4
}]
},
"meta": {}
}
GET https://api.particle.io/v1/products/1234/locations/123456
HTTP/1.1 200 OK
{
"location": {
"device_id": "1234567890abcdef",
"device_name" : "ice-cream-truck3",
"product_id": 343,
"groups": ["us-east", "truck"],
"gps_lock" : true,
"last_heard" : "2020-12-05T20:06:120Z",
"timestamps": ["2020-12-05T20:06:120Z"],
"geometry": {
"type": "Point",
"coordinates": [
34.548699645996094,
31.804855323809403
]
},
"properties": [{
"hd" : 36.6,
"acc_h": 5.0,
"speed": 13.5,
"temp": 77.4
}]
},
"meta": {}
}
GET /v1/products/:productIdOrSlug/config
Get the configuration values that are the default for the product
Product ID or slug.
$ curl https://api.particle.io/v1/products/1234/config -H "Authorization: Bearer :access_token"
GET https://api.particle.io/v1/products/1234/config
HTTP/1.1 200 OK
{
"configuration": {
"location": {
"radius": 1,
"interval_min": 30,
"interval_max": 300,
"min_publish": false
},
"imu_trig": {
"motion": "disable",
"high_g": "disable"
},
"rgb": {
"type": "tracker",
"direct": {
"red": 0,
"blue": 255,
"green": 0,
"brightness": 255
}
}
}
}
GET https://api.particle.io/v1/products/1234/config
HTTP/1.1 404 Not Found
{}
GET /v1/products/:productIdOrSlug/config/:deviceId
Get the configuration values that are specific to this device
Product ID or slug.
The device ID to query.
$ curl https://api.particle.io/v1/products/1234/config/abc123 -H "Authorization: Bearer :access_token"
The device's current confirmed configuration
The configuration this device will be updated to
GET https://api.particle.io/v1/products/1234/config/abc123
HTTP/1.1 200 OK
{
"configuration": {
"current": {
"imu_trig": {
"motion": "disable",
"high_g": "disable"
},
"location": {
"radius": 1,
"interval_min": 30,
"interval_max": 300,
"min_publish": false
}
},
"pending": {
"location": {
"radius": 10,
"interval_min": 30,
"interval_max": 300,
"min_publish": false
},
"imu_trig": {
"motion": "enable",
"high_g": "disable"
}
}
}
}
GET https://api.particle.io/v1/products/1234/config/abc123
HTTP/1.1 404 Not Found
{}
GET /v1/products/:productIdOrSlug/config
Get the possible values that can be configured for this product, in JSON Schema format
Must be set to "application/schema+json" for this endpoint
configuration:get
Product ID or slug.
$ curl https://api.particle.io/v1/products/1234/config \
-H "Accept: application/schema+json" \
-H "Authorization: Bearer :access_token"
GET https://api.particle.io/v1/products/1234/config
HTTP/1.1 200 OK
{
"$schema": "http://json-schema.org/draft-07/schema",
"properties": {
...
}
}
GET /v1/products/:productIdOrSlug/config/:deviceId
Get the possible values that can be configured for one device in this product, in JSON Schema format
Must be set to "application/schema+json" for this endpoint
configuration:get
Product ID or slug.
The device ID to query.
$ curl https://api.particle.io/v1/products/1234/config/abc123 \
-H "Accept: application/schema+json" \
-H "Authorization: Bearer :access_token"
GET https://api.particle.io/v1/products/1234/config/abc123
HTTP/1.1 200 OK
{
"$schema": "http://json-schema.org/draft-07/schema",
"properties": {
...
}
}
DELETE /v1/products/:productIdOrSlug/config
Delete configuration schema, use Tracker Edge defaults.
Must be set to "application/schema+json" for this endpoint.
configuration:update
Product ID or slug.
$ curl -X DELETE "https://api.particle.io/v1/products/1234/config" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/schema+json" \
-d '{}'
PUT https://api.particle.io/v1/products/1234/config
HTTP/1.1 204 OK
PUT /v1/products/:productIdOrSlug/config
Set configuration values that will become the default for the product. This will also update eligible devices with this updated configuration.
You should always get the entire configuration, change values, and set the whole configuration back. In HTTP REST APIs, POST and PUT do not merge changes with the existing data.
configuration:update
Product ID or slug.
an array of deviceIDs to limit this update to. If the request has no other content the devices will be reset to use the product defaults.
$ curl -X PUT https://api.particle.io/v1/products/1234/config \
-H "Content-Type: application/json" \
-H "Authorization: Bearer :access_token" \
-d "{\"location\":{\"radius\":5.0}}"
PUT https://api.particle.io/v1/products/1234/config
HTTP/1.1 202 OK
{}
PUT /v1/products/:productIdOrSlug/config
Set configuration schema that will become the default for the product.
This must be the entire schema, including the standard Particle parts; there is no merging of changes.
Must be set to "application/schema+json" for this endpoint.
configuration:update
Product ID or slug.
$ curl -X PUT "https://api.particle.io/v1/products/1234/config" \
-H "Authorization: Bearer ACCESS-TOKEN-HERE" \
-H "Content-Type: application/schema+json" \
-d '{
"$schema": "https://particle.io/draft-07/schema#",
"type": "object",
"title": "Fake Custom Schema",
"description": "A customized JSON schema for testing",
"required": [
"foo"
],
"properties": {
"foo": {
"$id": "#/properties/foo",
"type": "integer",
"title": "Foo",
"description": "A test setting named foo
",
"default": 1,
"examples": [1, 2, 3],
"minimum": 0
},
"bar": {
"$id": "#/properties/bar",
"type": "string",
"title": "Bar",
"description": "A test setting named bar
",
"default": "",
"examples": ["one", "two", "three"]
}
}
}'
PUT https://api.particle.io/v1/products/1234/config
HTTP/1.1 200 OK
{
"$schema": "https://particle.io/draft-07/schema#",
"type": "object",
"title": "Fake Custom Schema",
"description": "A customized JSON schema for testing",
"required": [
"foo"
],
"properties": {
"foo": {
"$id": "#/properties/foo",
"type": "integer",
"title": "Foo",
"description": "A test setting named foo
",
"default": 1,
"examples": [1, 2, 3],
"minimum": 0
},
"bar": {
"$id": "#/properties/bar",
"type": "string",
"title": "Bar",
"description": "A test setting named bar
",
"default": "",
"examples": ["one", "two", "three"]
}
}
}
PUT https://api.particle.io/v1/products/1234/config
HTTP/1.1 422 Bad Request
{
message: 'Invalid Schema',
description: 'data should NOT have additional properties',
violations: [
{
"keyword": "additionalProperties",
"dataPath": "",
"schemaPath": "#/additionalProperties",
"params": {
"additionalProperty": "nope"
},
"message": "should NOT have additional properties"
}
]
}
DELETE /v1/products/:productIdOrSlug/config/:deviceId
Delete device's configuration schema, use product's.
Must be set to "application/schema+json" for this endpoint.
configuration:update
Product ID or slug.
The device ID to delete the schema.
$ curl -X DELETE "https://api.particle.io/v1/products/1234/config/43210" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/schema+json" \
-d '{}'
PUT https://api.particle.io/v1/products/1234/config/43210
HTTP/1.1 204 OK
PUT /v1/products/:productIdOrSlug/config/:deviceId
Set some configuration values for the device that will override the product default.
Send an empty request to reset the device to product defaults.
Returns 200, 202 or 400 for various states
You should always get the entire configuration, change values, and set the whole configuration back. In HTTP REST APIs, POST and PUT do not merge changes with the existing data.
configuration:update
Product ID or slug.
Device ID
$ curl -X PUT https://api.particle.io/v1/products/1234/config/abc123 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer :access_token" \
-d "{\"location\":{\"radius\":5.0}}"
PUT https://api.particle.io/v1/products/1234/config/abc123
HTTP/1.1 200 OK
{}
PUT https://api.particle.io/v1/products/1234/config/abc123
HTTP/1.1 202 Accepted
{}
PUT https://api.particle.io/v1/products/1234/config/abc123
HTTP/1.1 400 Bad Request
{
error: 'device_rejected_configuration',
error_description: 'Configuration updates failed for some sections: {location: -19}, these sections were successful: imu_trig'
}
PUT /v1/products/:productIdOrSlug/config/:deviceId
Set configuration schema for the device.
This must be the entire schema, including the standard Particle parts; there is no merging of changes.
Must be set to "application/schema+json" for this endpoint.
configuration:update
Product ID or slug.
Device ID
$ curl -X PUT "https://api.particle.io/v1/products/1234/config/43210" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/schema+json" \
-d '{
"$schema": "https://particle.io/draft-07/schema#",
"type": "object",
"title": "Fake Custom Schema",
"description": "A customized JSON schema for testing",
"required": [
"foo"
],
"properties": {
"foo": {
"$id": "#/properties/foo",
"type": "integer",
"title": "Foo",
"description": "A test setting named foo
",
"default": 1,
"examples": [1, 2, 3],
"minimum": 0
},
"bar": {
"$id": "#/properties/bar",
"type": "string",
"title": "Bar",
"description": "A test setting named bar
",
"default": "",
"examples": ["one", "two", "three"]
}
}
}'
PUT https://api.particle.io/v1/products/1234/config/43210
HTTP/1.1 200 OK
{
"$schema": "https://particle.io/draft-07/schema#",
"type": "object",
"title": "Fake Custom Schema",
"description": "A customized JSON schema for testing",
"required": [
"foo"
],
"properties": {
"foo": {
"$id": "#/properties/foo",
"type": "integer",
"title": "Foo",
"description": "A test setting named foo
",
"default": 1,
"examples": [1, 2, 3],
"minimum": 0
},
"bar": {
"$id": "#/properties/bar",
"type": "string",
"title": "Bar",
"description": "A test setting named bar
",
"default": "",
"examples": ["one", "two", "three"]
}
}
}
PUT https://api.particle.io/v1/products/1234/config/43210
HTTP/1.1 422 Bad Request
{
message: 'Invalid Schema',
description: 'data should NOT have additional properties',
violations: [
{
"keyword": "additionalProperties",
"dataPath": "",
"schemaPath": "#/additionalProperties",
"params": {
"additionalProperty": "nope"
},
"message": "should NOT have additional properties"
}
]
}
POST /v1/logic/execute
Executes the provided logic function.
logic.functions:execute
Organization ID or Slug. Organization endpoint only.
Logic function code to debug
Type of code (always JavaScript)
Code to execute
Event to trigger the logic function
Event name
Event data
Device ID that triggered the event
Product ID that triggered the event
Optional API user to access Particle API
$ curl "https://api.particle.io/v1/logic/execute" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
--data @debug_function.json
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/logic/execute" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
--data @debug_function.json
POST /v1/logic/execute
HTTP/1.1 200 OK
{
"result": {
"status": "Success",
"logs": []
}
}
GET /v1/logic/functions
Lists all logic functions belonging to the specified Sandbox or organization.
logic.functions:list
Organization ID or Slug. Organization endpoint only.
Include today's stats
$ curl "https://api.particle.io/v1/logic/functions?today_stats=true" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/logic/functions?today_stats=true" \
-H "Authorization: Bearer :access_token"
GET /v1/logic/functions?today_stats=true
HTTP/1.1 200 OK
{
"logic_functions": [
{
"id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"owner_id": "user:deadbeef",
"version": 4,
"enabled": false,
"name": "My Logic Function",
"description": "",
"template_slug": null,
"source": {
"type": "JavaScript",
"code": "export default function main() {}"
},
"created_at": "2023-08-08T18:37:20.355177Z",
"updated_at": "2023-10-25T21:10:44.240143Z",
"created_by": "user:deadbeef",
"updated_by": "user:deadbeef",
"logic_triggers": [
{
"id": "08c6cfc4-e7d6-4b75-aa9e-8690d5c7aa5d",
"type": "Scheduled",
"logic_function_id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"enabled": true,
"version": 4,
"cron": "0 0 0 0 0",
"start_at": "2023-10-25T21:10:44.268743Z",
"end_at": null,
"last_scheduled_at": "2023-10-25T21:15:00Z",
"next_unscheduled_at": "2023-10-25T21:20:00Z"
}
],
"today_stats": {
"success": 0,
"failure": 0,
"timeout": 0
}
}
]
}
GET /v1/logic/functions/:logicFunctionId
Returns the specified logic function.
logic.functions:get
Organization ID or Slug. Organization endpoint only.
Logic function ID
$ curl "https://api.particle.io/v1/logic/functions/:logicFunctionId" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/logic/functions/:logicFunctionId" \
-H "Authorization: Bearer :access_token"
GET /v1/logic/functions/:logicFunctionId
HTTP/1.1 200 OK
{
"logic_function": {
"id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"owner_id": "user:deadbeef",
"version": 4,
"enabled": false,
"name": "My Logic Function",
"description": "",
"template_slug": null,
"source": {
"type": "JavaScript",
"code": "export default function main() {}"
},
"created_at": "2023-08-08T18:37:20.355177Z",
"updated_at": "2023-10-25T21:10:44.240143Z",
"created_by": "user:deadbeef",
"updated_by": "user:deadbeef",
"logic_triggers": [
{
"id": "08c6cfc4-e7d6-4b75-aa9e-8690d5c7aa5d",
"type": "Scheduled",
"logic_function_id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"enabled": true,
"version": 4,
"cron": "0 0 0 0 0",
"start_at": "2023-10-25T21:10:44.268743Z",
"end_at": null,
"last_scheduled_at": "2023-10-25T21:15:00Z",
"next_unscheduled_at": "2023-10-25T21:20:00Z"
}
]
}
}
POST /v1/logic/functions
Creates a logic function.
logic.functions:create
Organization ID or Slug. Organization endpoint only.
Logic function
$ curl "https://api.particle.io/v1/logic/functions" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
--data @logicFunction.json
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/logic/functions" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
--data @logicFunction.json
POST /v1/logic/functions
HTTP/1.1 201 Created
{
"logic_function": {
"id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"owner_id": "user:deadbeef",
"version": 4,
"enabled": false,
"name": "My Logic Function",
"description": "",
"template_slug": null,
"source": {
"type": "JavaScript",
"code": "export default function main() {}"
},
"created_at": "2023-08-08T18:37:20.355177Z",
"updated_at": "2023-10-25T21:10:44.240143Z",
"created_by": "user:deadbeef",
"updated_by": "user:deadbeef",
"logic_triggers": [
{
"id": "08c6cfc4-e7d6-4b75-aa9e-8690d5c7aa5d",
"type": "Scheduled",
"logic_function_id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"enabled": true,
"version": 4,
"cron": "0 0 0 0 0",
"start_at": "2023-10-25T21:10:44.268743Z",
"end_at": null,
"last_scheduled_at": "2023-10-25T21:15:00Z",
"next_unscheduled_at": "2023-10-25T21:20:00Z"
}
]
}
}
PUT /v1/logic/functions/:logicFunctionId
Updates the logic function.
logic.functions:update
Organization ID or Slug. Organization endpoint only.
Logic function ID
Logic function
$ curl -X PUT "https://api.particle.io/v1/logic/functions/:logicFunctionId" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
--data @logicFunction.json
$ curl -X PUT "https://api.particle.io/v1/orgs/:orgSlugOrId/logic/functions/:logicFunctionId" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
--data @logicFunction.json
PUT /v1/logic/functions/:logicFunctionId
HTTP/1.1 201 Created
{
"logic_function": {
"id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"owner_id": "user:deadbeef",
"version": 4,
"enabled": false,
"name": "My Logic Function",
"description": "",
"template_slug": null,
"source": {
"type": "JavaScript",
"code": "export default function main() {}"
},
"created_at": "2023-08-08T18:37:20.355177Z",
"updated_at": "2023-10-25T21:10:44.240143Z",
"created_by": "user:deadbeef",
"updated_by": "user:deadbeef",
"logic_triggers": [
{
"id": "08c6cfc4-e7d6-4b75-aa9e-8690d5c7aa5d",
"type": "Scheduled",
"logic_function_id": "79c1c82b-6dc5-49a1-b678-559b3e53a44d",
"enabled": true,
"version": 4,
"cron": "0 0 0 0 0",
"start_at": "2023-10-25T21:10:44.268743Z",
"end_at": null,
"last_scheduled_at": "2023-10-25T21:15:00Z",
"next_unscheduled_at": "2023-10-25T21:20:00Z"
}
],
"today_stats": {
"success": 0,
"failure": 0,
"timeout": 0
}
}
}
DELETE /v1/logic/functions/:logicFunctionId
Deletes the specified logic function.
logic.functions:remove
Organization ID or Slug. Organization endpoint only.
Logic function ID
$ curl -X DELETE "https://api.particle.io/v1/logic/functions/:logicFunctionId" \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE "https://api.particle.io/v1/orgs/:orgSlugOrId/logic/functions/:logicFunctionId" \
-H "Authorization: Bearer :access_token"
DELETE /v1/logic/functions/:logicFunctionId
HTTP/1.1 204 No content
GET /v1/logic/functions/:logicFunctionId/runs
Lists all runs for the specified logic function.
logic.runs:list
Organization ID or Slug. Organization endpoint only.
Logic function ID
$ curl "https://api.particle.io/v1/logic/functions/:logicFunctionId/runs" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/logic/functions/:logicFunctionId/runs" \
-H "Authorization: Bearer :access_token"
GET /v1/logic/functions/:logicFunctionId/runs
HTTP/1.1 200 OK
{
"logic_runs": [
{
"id": "f1540276-63df-44a7-9f1b-b0dfec9640ea",
"owner_id": "user:deadbeef",
"logic_function_id": "f3635877-3106-49c0-84ea-28781d9371fe",
"logic_trigger_type": "Scheduled",
"logic_trigger_id": "899944c2-ff3f-4f6a-a135-c4bc624ec382",
"status": "Success",
"started_at": "2023-11-07T18:20:59.462214Z",
"finished_at": "2023-11-07T18:20:59.581605Z",
"log_filename": "user:deadbeef/function-f3635877-3106-49c0-84ea-28781d9371fe/Scheduled-899944c2-ff3f-4f6a-a135-c4bc624ec382/1699381259462:1699381259581_1f32a920-7690-41c0-9585-0bbcab7846e9.json"
}
]
}
GET /v1/logic/functions/:logicFunctionId/runs/:logicRunId
Returns the specified logic function run.
logic.runs:get
Organization ID or Slug. Organization endpoint only.
Logic function ID
Logic run ID
$ curl "https://api.particle.io/v1/logic/functions/:logicFunctionId/runs/:logicRunId" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/logic/functions/:logicFunctionId/runs/:logicRunId" \
-H "Authorization: Bearer :access_token"
GET /v1/logic/functions/:logicFunctionId/runs/:logicRunId
HTTP/1.1 200 OK
{
"logic_run": {
"id": "f1540276-63df-44a7-9f1b-b0dfec9640ea",
"owner_id": "users:deadbeef",
"logic_function_id": "f3635877-3106-49c0-84ea-28781d9371fe",
"logic_trigger_type": "Scheduled",
"logic_trigger_id": "899944c2-ff3f-4f6a-a135-c4bc624ec382",
"status": "Success",
"started_at": "2023-11-07T18:20:59.462214Z",
"finished_at": "2023-11-07T18:20:59.581605Z",
"log_filename": "users:deadbeef/function-f3635877-3106-49c0-84ea-28781d9371fe/Scheduled-899944c2-ff3f-4f6a-a135-c4bc624ec382/1699381259462:1699381259581_1f32a920-7690-41c0-9585-0bbcab7846e9.json"
}
}
GET /v1/logic/functions/:logicFunctionId/runs/:logicRunId/logs
Returns the specified logic function run logs.
logic.logs:list
Organization ID or Slug. Organization endpoint only.
Logic function ID
Logic run ID
$ curl "https://api.particle.io/v1/logic/functions/:logicFunctionId/runs/:logicRunId/logs" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/logic/functions/:logicFunctionId/runs/:logicRunId/logs" \
-H "Authorization: Bearer :access_token"
GET /v1/logic/functions/:logicFunctionId/runs/:logicRunId/logs
HTTP/1.1 200 OK
{
"logic_run_logs": {
"logs": [
{
"level": "Info",
"timestamp": "2023-11-07T18:20:59.470Z",
"args": [
"Hello"
]
}
]
}
}
GET /v1/logic/functions/:logicFunctionId/stats
Returns the specified logic function stats.
logic.stats:list
Organization ID or Slug. Organization endpoint only.
Logic function ID
$ curl "https://api.particle.io/v1/logic/functions/:logicFunctionId/stats" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/logic/functions/:logicFunctionId/stats" \
-H "Authorization: Bearer :access_token"
GET /v1/logic/functions/:logicFunctionId/stats
HTTP/1.1 200 OK
{
"logic_function_stats": [
{
"date": "20231106",
"success": 175,
"failure": 168,
"timeout": 0
}
]
}
GET /v1/ledgers
Lists all ledger definitions belonging to the Sandbox or organization.
ledger.definitions:list
Organization ID or Slug. Organization endpoint only.
Page number
Number of definitions per page
Filter for archived definitions
$ curl "https://api.particle.io/v1/ledgers" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers" \
-H "Authorization: Bearer :access_token"
GET /v1/ledgers
HTTP/1.1 200 OK
{
"ledgers": [
{
"scope": "Owner",
"name": "My Ledger",
"description": "My Ledger Description",
"direction": "Downstream",
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
"archived_at": "2023-01-01T00:00:00.000Z" | null
}
],
"meta": {
"page": 1,
"per_page": 100,
"total_pages": 1,
"total": 1
}
}
GET /v1/ledgers/:ledgerName
Returns the specified ledger definition.
ledger.definitions:get
Organization ID or Slug. Organization endpoint only.
Ledger name
$ curl "https://api.particle.io/v1/ledgers/:ledgerName" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/ledgers/:ledgerName" \
-H "Authorization: Bearer :access_token"
GET /v1/ledgers/:ledgerName
HTTP/1.1 200 OK
{
"ledger": {
"scope": "Owner",
"name": "My Ledger",
"description": "My Ledger Description",
"direction": "Downstream",
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
"archived_at": "2023-01-01T00:00:00.000Z" | null
}
}
POST /v1/ledgers
Creates a ledger definition.
ledger.definitions:create
Organization ID or Slug. Organization endpoint only.
Ledger definition
$ curl "https://api.particle.io/v1/ledgers" \
-H "Authorization: Bearer :access_token" \
--data @definition.json
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers" \
-H "Authorization: Bearer :access_token" \
--data @definition.json
POST /v1/ledgers
HTTP/1.1 201 Created
{
"ledger": {
"scope": "Owner",
"name": "My Ledger",
"description": "My Ledger Description",
"direction": "Downstream",
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
"archived_at": "2023-01-01T00:00:00.000Z" | null
}
}
PUT /v1/ledgers/:ledgerName
Updates the ledger definition.
ledger.definitions:update
Organization ID or Slug. Organization endpoint only.
Ledger name
Ledger definition
$ curl -X PUT "https://api.particle.io/v1/ledgers/:ledgerName" \
-H "Authorization: Bearer :access_token" \
--data @definition.json
$ curl -X PUT "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers/:ledgerName" \
-H "Authorization: Bearer :access_token" \
--data @definition.json
PUT /v1/ledgers/:ledgerName
HTTP/1.1 201 Created
{
"ledger": {
"scope": "Owner",
"name": "My Ledger",
"description": "My Ledger Description",
"direction": "Downstream",
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
"archived_at": "2023-01-01T00:00:00.000Z" | null
}
}
DELETE /v1/ledgers/:ledgerName
Archives a ledger definition.
ledger.definitions:archive
Organization ID or Slug. Organization endpoint only.
Ledger name
$ curl -X DELETE "https://api.particle.io/v1/ledgers/:ledgerName" \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers/:ledgerName" \
-H "Authorization: Bearer :access_token"
DELETE /v1/ledgers/:ledgerName
HTTP/1.1 204 No content
GET /v1/ledgers/:ledgerName/instances
Lists all ledger instances.
ledger.instances:list
Organization ID or Slug. Organization endpoint only.
Ledger name
Page number
Number of instances per page
$ curl "https://api.particle.io/v1/ledgers/:ledgerName/instances" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers/:ledgerName/instances" \
-H "Authorization: Bearer :access_token"
GET /v1/ledgers/:ledgerName/instances
HTTP/1.1 200 OK
{
"instances": [
{
"name": "prodledger",
"scope": {
"type": "Product",
"value": "123",
"name": "My Product"
},
"size_bytes": 1234,
"data": {},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
}, {
"name": "prodledger",
"scope": {
"type": "Product",
"value": "456",
"not_owned": true
},
"size_bytes": 1234,
"data": {},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
}
],
"meta": {
"page": 1,
"per_page": 100,
"total_pages": 1,
"total": 1
}
}
GET /v1/ledgers/:ledgerName/instances/:scopeValue
Returns the specified ledger instance.
ledger.instances:get
Organization ID or Slug. Organization endpoint only.
Ledger name
Scope value
$ curl "https://api.particle.io/v1/ledgers/:ledgerName/instances/:scopeValue" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/ledgers/:ledgerName/instances/:scopeValue" \
-H "Authorization: Bearer :access_token"
GET /v1/ledgers/:ledgerName/instances/:scopeValue
HTTP/1.1 200 OK
{
"instance": {
"scope": {
"type": "Product",
"value": "123",
},
"name": "prodledger",
"size_bytes": 1234,
"data": {},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
}
}
GET /v1/ledgers/:ledgerName/instances/:scopeValue/versions/:version
Returns the specified version of a ledger instance.
ledger.instances.versions:get
Organization ID or Slug. Organization endpoint only.
Ledger name
Scope value
Version ID
$ curl "https://api.particle.io/v1/ledgers/:ledgerName/instances/:scopeValue/versions/:version" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/ledgers/:ledgerName/instances/:scopeValue/versions/:version" \
-H "Authorization: Bearer :access_token"
GET /v1/ledgers/:ledgerName/instances/:scopeValue/versions/:version
HTTP/1.1 200 OK
{
"instance": {
"scope": {
"type": "Product",
"value": "123",
},
"name": "prodledger",
"size_bytes": 1234,
"data": {},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
}
}
PUT /v1/ledgers/:ledgerName/instances/:scopeValue
Sets the data of the specified ledger instance.
ledger.instances:set
Organization ID or Slug. Organization endpoint only.
Ledger name
Scope value
Ledger instance data
$ curl -X PUT "https://api.particle.io/v1/ledgers/:ledgerName/instances/:scopeValue" \
-H "Authorization: Bearer :access_token" \
--data @data.json
$ curl -X PUT "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers/:ledgerName/instances/:scopeValue" \
-H "Authorization: Bearer :access_token" \
--data @data.json
PUT /v1/ledgers/:ledgerName/instances/:scopeValue
HTTP/1.1 201 Created
{
"instance": {
"scope": {
"type": "Product",
"value": "123",
},
"name": "prodledger",
"size_bytes": 1234,
"data": {
"foo": "bar"
},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
}
}
DELETE /v1/ledgers/:ledgerName/instances/:scopeValue
Deletes the specified ledger instance.
ledger.instances:remove
Organization ID or Slug. Organization endpoint only.
Ledger name
Scope value
$ curl -X DELETE "https://api.particle.io/v1/ledgers/:ledgerName/instances/:scopeValue" \
-H "Authorization: Bearer :access_token"
$ curl -X DELETE "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers/:ledgerName/instances/:scopeValue" \
-H "Authorization: Bearer :access_token"
DELETE /v1/ledgers/:ledgerName/instances/:scopeValue
HTTP/1.1 204 No content
GET /v1/ledgers/:ledgerName/instances/:scopeValue/versions
Lists all ledger instance versions.
ledger.instances.versions:list
Organization ID or Slug. Organization endpoint only.
Ledger name
Scope value
List only versions replaced before this date
List only versions replaced after this date
$ curl "https://api.particle.io/v1/ledgers/:ledgerName/instances/:scopeValue/versions" \
-H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers/:ledgerName/instances/:scopeValue/versions" \
-H "Authorization: Bearer :access_token"
GET /v1/ledgers/:ledgerName/instances/:scopeValue/versions
HTTP/1.1 200 OK
{
"versions": [
{
"name": "prodledger",
"scope": {
"type": "Product",
"value": "123",
"name": "My Product"
},
"size_bytes": 1234,
"data": {},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
}, {
"name": "prodledger",
"scope": {
"type": "Product",
"value": "123",
},
"size_bytes": 1234,
"data": {},
"updated_at": "2023-01-01T00:00:00.000Z",
"created_at": "2023-01-01T00:00:00.000Z",
"replaced_at": "2023-11-28T15:02:04.799Z"
}
],
"meta": {
"has_more": false
}
}
GET /v1/products/:productIdOrSlug/metrics/online
Reports the number of devices online in this product.
Each time bucket contains:
count
: the number of devices with an active cloud connection.Devices that recently went offline (due to being powered off or losing network connectivity) will be counted as online until the device misses sending a keep-alive message to the cloud. This is typically 25 seconds for Wi-Fi networks and 23 minutes for cellular networks.
Can be filtered to include only devices with a certain firmware version, Device OS version or in a certain group.
metrics.online:get
Product ID or slug.
DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.
DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.
Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.
Filter for this product firmware version.
Filter for this Device OS version.
Filter for this device group.
$ curl "https://api.particle.io/v1/products/12345/metrics/online?start_date=2023-04-01T00:00:00.000Z&end_date=2023-04-03T00:00:00.000Z&bucket_size=3600" \
-H "Authorization: Bearer :access_token"
An array of online devices metrics
The start of the time bucket. Date in ISO8601 format.
The number of devices online in this bucket.
GET /v1/products/12345/metrics/online
HTTP/1.1 200 OK
{
"online": [
{
"time": "2024-04-01T00:00:00.000Z",
"count": 37
},
{
"time": "2024-04-01T01:00:00.000Z",
"count": 42
},
...
]
}
GET /v1/products/:productIdOrSlug/metrics/events
Reports each time a device publishes an event in this product.
Each time bucket contains counts of:
received
: the cloud received an event from a device.Can be filtered to include only events from devices with a certain firmware version, Device OS version or in a certain group.
metrics.events:get
Product ID or slug.
DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.
DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.
Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.
Filter for this product firmware version.
Filter for this Device OS version.
Filter for this device group.
$ curl "https://api.particle.io/v1/products/12345/metrics/events?start_date=2023-04-01T00:00:00.000Z&end_date=2023-04-03T00:00:00.000Z&bucket_size=3600" \
-H "Authorization: Bearer :access_token"
An array of events metrics
The start of the time bucket. Date in ISO8601 format.
The number of events received in this bucket.
GET /v1/products/12345/metrics/events
HTTP/1.1 200 OK
{
"events": [
{
"time": "2024-04-01T00:00:00.000Z",
"received": 256
},
{
"time": "2024-04-01T01:00:00.000Z",
"received": 1024
},
...
]
}
GET /v1/products/:productIdOrSlug/metrics/integration
Reports outbound integration requests that are sent on behalf of this product fleet and the outcome.
Each time bucket contains counts of (keys with a value of 0 will be omitted):
success
: the integration request was accepted by the destination service (2xx response code).failure
: the integration request was rejected by the destination service (network error, 4xx or 5xx response code) after 3 attempts.sleep
(skipped): the integration request was not attempted because there have been too many previous failures in rapid succession.Can be filtered to include only integrations triggered by devices with a certain firmware version, Device OS version or in a certain group.
metrics.integrations:get
Product ID or slug.
DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.
DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.
Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.
Filter for this product firmware version.
Filter for this Device OS version.
Filter for this device group.
$ curl "https://api.particle.io/v1/products/12345/metrics/integration?start_date=2023-04-01T00:00:00.000Z&end_date=2023-04-03T00:00:00.000Z&bucket_size=3600" \
-H "Authorization: Bearer :access_token"
An array of integration metrics
The start of the time bucket. Date in ISO8601 format.
The number of successful integrations in this bucket.
The number of failed integrations in this bucket.
The number of skipped integrations in this bucket.
GET /v1/products/12345/metrics/integration
HTTP/1.1 200 OK
{
"integrations": [
{
"time": "2024-04-01T00:00:00.000Z",
"success": 40,
"failure": 3,
"sleep": 1
},
{
"time": "2024-04-01T01:00:00.000Z",
"success": 40,
"failure": 3,
"sleep": 1
},
...
]
}
GET /v1/products/:productIdOrSlug/metrics/functions
Reports each time a Particle.function()
in firmware is called on a device in this product and the outcome.
Each time bucket contains counts of (keys with a value of 0 will be omitted):
success
: the target device successfully received and responded to the function call.failure
: the target device was unable to process the function call, or was unreachable by the cloud.offline
: the function call attempt was skipped because the device was not connected to the cloud at the time the call was made.Can be filtered to include only function calls for devices with a certain firmware version, Device OS version or in a certain group.
metrics.functions:get
Product ID or slug.
DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.
DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.
Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.
Filter for this product firmware version.
Filter for this Device OS version.
Filter for this device group.
$ curl "https://api.particle.io/v1/products/12345/metrics/functions?start_date=2023-04-01T00:00:00.000Z&end_date=2023-04-03T00:00:00.000Z&bucket_size=3600" \
-H "Authorization: Bearer :access_token"
An array of functions metrics
The start of the time bucket. Date in ISO8601 format.
The number of successful function calls in this bucket.
The number of failed function calls in this bucket.
The number of skipped function calls due to device being offline in this bucket.
GET /v1/products/12345/metrics/functions
HTTP/1.1 200 OK
{
"functions": [
{
"time": "2024-04-01T00:00:00.000Z",
"success": 10,
"failure": 3,
"offline": 42
},
{
"time": "2024-04-01T01:00:00.000Z",
"success": 10,
"failure": 3,
"offline": 42
},
...
]
}
GET /v1/products/:productIdOrSlug/metrics/variables
Reports each time a Particle.variable()
in firmware is read on a device in this product and the outcome.
Each time bucket contains counts of (keys with a value of 0 will be omitted):
success
: the target device successfully received and responded to the variable request.failure
: the target device was unable to process the variable request, or was unreachable by the cloud.offline
: the variable request was skipped because the device was not connected to the cloud at the time the call was made.Can be filtered to include only variable requests for devices with a certain firmware version, Device OS version or in a certain group.
metrics.variables:get
Product ID or slug.
DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.
DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.
Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.
Filter for this product firmware version.
Filter for this Device OS version.
Filter for this device group.
$ curl "https://api.particle.io/v1/products/12345/metrics/variables?start_date=2023-04-01T00:00:00.000Z&end_date=2023-04-03T00:00:00.000Z&bucket_size=3600" \
-H "Authorization: Bearer :access_token"
An array of variables metrics
The start of the time bucket. Date in ISO8601 format.
The number of successful variable requests in this bucket.
The number of failed variable requests in this bucket.
The number of skipped variable requests due to device being offline in this bucket.
GET /v1/products/12345/metrics/variables
HTTP/1.1 200 OK
{
"variables": [
{
"time": "2024-04-01T00:00:00.000Z",
"success": 10,
"failure": 3,
"offline": 42
},
{
"time": "2024-04-01T01:00:00.000Z",
"success": 10,
"failure": 3,
"offline": 42
},
...
]
}
If you wish to provide a mobile app or web app for your customers, we recommend that you implement your own user management features on your front and back-end. You may want to use common third-party login features such as login with Google, Facebook, Twitter, etc. instead of implementing your own from scratch, but this not required. Implementing user management this way will eliminate the need for customer-specific Particle access tokens, which will greatly simplify the implementation of your front and back-end.
POST /v1/products/:productIdOrSlug/customers
Create a customer for a product. An access token of a user that belongs to the product is required. The email
field can contain a unique identifier instead but some platform functionalities might not work (i.e. sending a password reset email).
Product ID or Slug
Email Address or a unique identifier
Password
POST /v1/products/photon/customers
HTTP/1.1 201 OK
{
"token_type": "bearer",
"access_token": "92b6d13edaab936b016d54266a46134160f087e8",
"refresh_token": "14b4d13edaab634b019d54265a46132160f017e8",
"expires_in": 7776000
}
POST /v1/products/:productIdOrSlug/customers
Create a customer for a product using OAuth client credentials grant type. This is the way you should hit the POST
customers endpoint if you are creating customers from your server (two-legged authentication), or from a mobile application.
In this case, you may create a customer without a password, by passing the no_password: true
flag.
You must give a valid product OAuth client ID and secret in HTTP Basic Auth or in the client_id
and client_secret
parameters.
HTTP Basic Auth where username is the OAuth client ID and password is the OAuth client secret.
Product ID or Slug
OAuth client ID. Required if no Authorization header is present.
OAuth client secret. Required if no Authorization header is present.
Email Address
Password
For two-legged authentication, only required if you are creating password-less customers.
POST /v1/products/photon/customers
HTTP/1.1 201 OK
{
"token_type": "bearer",
"access_token": "92b6d13edaab936b016d54266a46134160f087e8",
"refresh_token": "14b4d13edaab634b019d54265a46132160f017e8",
"expires_in": 7776000
}
POST /v1/products/:productIdOrSlug/customers
Create a customer for a product using OAuth implicit grant type. This is the way you should hit the POST
customers endpoint if you are creating customers from a web browser. After a successful POST
, the customer
access token will be appended as a hash to the redirect URI associated with the client credentials provided. For this grant type, you must also pass response_type: token
.
You must give a valid product OAuth client ID in HTTP Basic Auth or in the client_id
parameter. Do not pass the OAuth client secret when creating customers from a web browser.
HTTP Basic Auth where username is the OAuth client ID and password is blank.
Product ID or Slug
OAuth client ID. Required if no Authorization header is present.
Email Address
Password
OAuth response type. Should only be included for implicit grant type and should be set to token
.
POST /v1/products/photon/customers
HTTP/1.1 201 OK
GET /v1/products/:productIdOrSlug/customers
List Customers for a product.
customers:list
Product ID or Slug
List of Customers
List of Devices that belong to those customers
Customer ID
Username
List of Device IDs
Device ID
Product ID
Last known IP Address
Firmware Version
Whether the device is currently online or not
GET /v1/products/photon
HTTP/1.1 200 OK
{
"customers": [
{
"id": "01234567890ABCDEF",
"full_name": "Bob Loblaw",
"username": "bob@loblaw.net",
"devices": ["0123456789abcdef01234567"]
}
],
"devices": [
{
"id": "0123456789abcdef01234567",
"product_id": 6,
"last_ip_address": "127.0.0.1",
"firmware_version": 1,
"online": true
}
],
"meta": {
"total_pages": 4
}
}
POST /oauth/token
Creates a token scoped to a customer for your organization.
You must give a valid product OAuth client ID and secret in HTTP Basic Auth or in the client_id
and client_secret
parameters.
Must be set to application/x-www-form-urlencoded
HTTP Basic Auth where username is the OAuth client ID and password is the OAuth client secret.
OAuth client ID. Required if no Authorization header is present.
OAuth client secret. Required if no Authorization header is present.
OAuth grant type. Must be client_credentials
.
How many seconds the token will be valid for. 0
means forever. Short lived tokens are better for security.
When should the token expire? This should be an ISO8601 formatted date string.
The customer to scope this token to. Format of customer=jane@example.com
.
$ curl https://api.particle.io/oauth/token \
-u my-org-client-1234:long-secret \
-d grant_type=client_credentials \
-d "scope=customer=jane@example.com"
The magical token you will use for all the other requests
Always set to "Bearer"
The number of seconds this token is valid for. 0
means forever.
Used to generate a new access token when it has expired.
POST /oauth/token
HTTP/1.1 200 OK
{
"access_token": "254406f79c1999af65a7df4388971354f85cfee9",
"token_type": "bearer",
"expires_in": 7776000,
"refresh_token": "b5b901e8760164e134199bc2c3dd1d228acf2d90"
}
PUT /v1/products/:productIdOrSlug/customers/:customerEmail
Update the account password for a customer. Only relevant for non-shadow customers that have a password saved in Particle's system. Must be called with an access token that has access to the product, not a customer access token.
customers:update
Product ID or Slug
Email of the customer account that you'd like to update
The new password for the customer
$ curl -X PUT "https://api.particle.io/v1/products/:productIdOrSlug/customers/test@company.com" \
-H "Authorization: Bearer :access_token" \
-d password=newpassword
PUT /v1/products/:productIdOrSlug/customers/:customerEmail
HTTP/1.1 200 OK
{"ok": true}
DELETE /v1/products/:productIdOrSlug/customers/:customerEmail
Delete a customer in a product. Will also revoke all of this customer's access tokens, pending device claim codes and activation codes.
customers:remove
Product ID or Slug
Email of the customer account that you'd like to remove
$ curl -X DELETE "https://api.particle.io/v1/products/:productIdOrSlug/customers/test@company.com" \
-H "Authorization: Bearer :access_token"
DELETE /v1/products/:productIdOrSlug/customers/:customerEmail
HTTP/1.1 200 OK
{"ok": true}
If you wish to provide a mobile app or web app for your customers, we recommend that you implement your own user management features on your front and back-end. We do not recommend using simple auth or two-legged shadow customers in most cases now.
Simple Auth can be used as a simpler alternative, however you will need to provide an additional service if you want to allow your customers to be able to reset their password by email. The process works like this:
PUT /v1/products/:productIdOrSlug/customers/:customerEmail
{password: <new_password>, access_token: <your_token>}
We've provided a sample app using Heroku and PostgreSQL. This can be used as-is, or you can use it as an example of how to add support into your existing server infrastructure.
GET /v1/user/service_agreements
Get the service agreements related to a user
Service agreement Unique ID
Object type
Service agreement attributes
Service agreement owner
Service agreement type
Billing period duration
Indicates if the service agreement is active
Date when the service agreement started
service Agreements ends date
Current billing period start date
Usage summary for the period
Indicates if the device limit was reached
Info about the connectivity devices grouped by device type
All related with the selected pricing model
Rates limits and consumption period
Device limits and consumption period
Message limits and consumption period
Device data limits and consumption period
GET /v1/orgs/particle/service_agreements
HTTP/1.1 200 OK
{
"data":[
{
"id":"1",
"type":"service_agreement",
"attributes":{
"owner_id":"abc123",
"owner_type":"individual",
"name":"Sandbox",
"agreement_type":"developer",
"duration":"monthly",
"state":"active",
"starts_on":"2021-04-08",
"ends_on":null,
"current_billing_period_start":"2021-04-08",
"current_billing_period_end":"2021-05-07",
"next_billing_period_start":"2021-05-08",
"current_usage_summary":{
"device_limit_reached":false,
"connectivity":{
"all":{
"owned_devices":0,
"billable_devices":0,
"device_data":0,
"device_messages":0
},
"wifi":{
"owned_devices":0,
"billable_devices":0,
"device_data":null,
"device_messages":0
},
"cellular":{
"owned_devices":0,
"billable_devices":0,
"device_data":0,
"device_messages":0
},
"asset_tracker":{
"owned_devices":0,
"billable_devices":0,
"device_data":0,
"device_messages":0
}
}
},
"pricing_terms":{
"rates":{
"all_platforms":{
"duration":"monthly",
"per_block":0
},
"pricing_model_version":"tier2021.1"
},
"device":{
"name":"commercial_model:developer:device",
"duration":"monthly",
"max_devices":100
},
"messaging":{
"name":"commercial_model:developer:messaging",
"duration":"monthly",
"max_messages":100000
},
"device_data":{
"uom":"bytes",
"name":"commercial_model:developer:device_data",
"duration":"monthly",
"max_data":45000000,
"device_data":45000000,
"devices_cap":45000000,
"cap_exception":true
}
}
}
}
]
}
GET /v1/orgs/:orgIdOrSlug/service_agreements
Get the service agreements related to an organization
service_agreements:list
Org ID or Slug
Service agreement Unique ID
Object type
Service agreement attributes
Service agreement owner
Service agreement type
Billing period duration
Indicates if the service agreement is active
Date when the service agreement started
service Agreements ends date
Current billing period start date
Usage summary for the period
Indicates if the device limit was reached
Info about the connectivity devices grouped by device type
All related with the selected pricing model
Rates limits and consumption period
Device limits and consumption period
Message limits and consumption period
Device data limits and consumption period
Email address for enterprise support
GET /v1/orgs/particle/service_agreements
HTTP/1.1 200 OK
{
"data":[{
"id":"1",
"type":"service_agreement",
"attributes":{
"owner_id":"abc123",
"owner_type":"organization",
"name":"Enterprise Plan",
"agreement_type":"enterprise",
"duration":"annual",
"state":"active",
"starts_on":"2021-01-01",
"ends_on":"2026-01-01",
"current_billing_period_start":"2021-01-01",
"current_billing_period_end":"2021-12-31",
"next_billing_period_start":"2022-01-01",
"current_usage_summary":{
"device_limit_reached":false,
"connectivity":{
"all":{
"owned_devices":1,
"billable_devices":1,
"device_data":56789012,
"device_messages":1234567
},
"wifi":{
"owned_devices":1,
"billable_devices":1,
"device_data":null,
"device_messages":123456
},
"cellular":{
"owned_devices":1,
"billable_devices":1,
"device_data":12345,
"device_messages":123456
},
"asset_tracker":{
"owned_devices":1,
"billable_devices":1,
"device_data":12345678,
"device_messages":123456
}
}
},
"pricing_terms":{
"device_data":{
"uom":"bytes",
"name":"commercial_model:enterprise:device_data",
"cellular":{
"max_data":12000000000
},
"duration":"annual",
"asset_tracker":{
"max_data":12000000000
}
},
"rates":{
"wifi":{
"tier":0,
"duration":"annual",
"list_price":1234
},
"cellular":{
"tier":3,
"duration":"annual",
"list_price":1234
},
"asset_tracker":{
"tier":3,
"duration":"annual",
"list_price":123456
},
"pricing_model_version":"tier2021.1"
},
"messaging":{
"name":"commercial_model:enterprise:messaging",
"wifi":{
"max_messages":46800000
},
"cellular":{
"max_messages":182400000
},
"duration":"annual",
"asset_tracker":{
"max_messages":237120000
}
},
"device":{
"name":"commercial_model:enterprise:device",
"wifi":{
"max_devices":1500
},
"cellular":{
"max_devices":1810
},
"duration":"monthly",
"asset_tracker":{
"max_devices":1810
}
},
"support":{
"account_rep":"support@example.com"
}
}
}
}
]
}
GET /v1/user/usage_reports/:usageReportId
Get a single usage report related to the user. Expect "download_url" to be present only when the usage report has an "available" state.
The usage report ID
$ curl "https://api.particle.io/v1/user/usage_reports/:userReportId" \
-H "Authorization: Bearer :access_token"
Usage Report Unique ID
Object type
Usage Report attributes
Usage Report current state
Service Agreement Unique ID
The start of the date period to query
The end of the date period to query
UTC timestamp of when the Usage Report request was created
UTC timestamp of when the Usage Report file expires
Usage Report type
Usage Report parameters
List of Device Unique IDs
List of Product Unique IDs
List of emails to send the report via email
Usage Report file expirable download URL
GET /v1/user/usage_reports/:usageReportId
HTTP/1.1 200 OK
{
"data": {
"id": "1",
"type": "usage_report",
"attributes": {
"state": "pending",
"service_agreement_id": 1,
"date_period_start": "2022-01-01",
"date_period_end": "2022-02-01",
"created_at": "2022-01-18 13:43:23 -0800",
"expires_at": null,
"report_type": "devices",
"report_params": {
"devices": [
"device1",
"device2"
],
"products": [],
"recipient_list": [
"your@email.com"
]
},
"download_url": null
}
}
GET /v1/orgs/:orgSlugOrId/usage_reports/:usageReportId
Get a single usage report related to an organization. Expect "download_url" to be present only when the usage report has an "available" state.
The user must be an active member of the organization.
service_agreements.usage_reports:get
The usage report ID
Organization Slug or ID
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/usage_reports/:usageReportId" \
-H "Authorization: Bearer :access_token"
Usage Report Unique ID
Object type
Usage Report attributes
Usage Report current state
Service Agreement Unique ID
The start of the date period to query
The end of the date period to query
UTC timestamp of when the Usage Report request was created
UTC timestamp of when the Usage Report file expires
Usage Report type
Usage Report parameters
List of Device Unique IDs
List of Product Unique IDs
List of emails to send the report via email
Usage Report file expirable download URL
GET /v1/orgs/:orgSlugOrId/usage_reports/:usageReportId
HTTP/1.1 200 OK
{
"data": {
"id": "1",
"type": "usage_report",
"attributes": {
"state": "pending",
"service_agreement_id": 1,
"date_period_start": "2022-01-01",
"date_period_end": "2022-02-01",
"created_at": "2022-01-18 13:43:23 -0800",
"expires_at": null,
"report_type": "devices",
"report_params": {
"devices": [
"device1",
"device2"
],
"products": [],
"recipient_list": [
"your@email.com"
]
},
"download_url": null
}
}
POST /v1/user/service_agreements/:serviceAgreementId/usage_reports
Request a new usage report related to the user service agreement.
The usage report will be processed asynchronously. Expect its "state" to change throughout time.
service_agreements.usage_reports:create
Service Agreement ID
One of the supported report types, "devices" or "products"
The start of the date period to query
The end of the date period to query
An optional array of Device IDs
An optional array of Product IDs
$ curl -X POST "https://api.particle.io/v1/user/service_agreements/:serviceAgreementId/usage_reports" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{
"report_type": "devices",
"date_period_start": "2022-01-01",
"date_period_end": "2022-01-31",
"devices": ["device1", "device2"]
}'
Usage Report Unique ID
Object type
Usage Report attributes
Usage Report current state
Service Agreement Unique ID
The start of the date period to query
The end of the date period to query
UTC timestamp of when the Usage Report request was created
UTC timestamp of when the Usage Report file expires
Usage Report type
Usage Report parameters
List of Device Unique IDs
List of Product Unique IDs
List of emails to send the report via email
Usage Report file expirable download URL
POST /v1/user/service_agreements/:serviceAgreementId/usage_reports/
HTTP/1.1 202 OK
{
"data": {
"id": "1",
"type": "usage_report",
"attributes": {
"state": "pending",
"service_agreement_id": 1,
"date_period_start": "2022-01-01",
"date_period_end": "2022-01-31",
"created_at": "2022-01-18 13:43:23 -0800",
"expires_at": null,
"report_type": "devices",
"report_params": {
"devices": [
"device1",
"device2"
],
"products": [],
"recipient_list": [
"your@email.com"
]
},
"download_url": null
}
}
POST /v1/orgs/:orgSlugOrId/service_agreements/:serviceAgreementId/usage_reports
Request a new usage report related to the organization service agreement.
The usage report will be processed asynchronously. Expect its "state" to change throughout time.
The user must be an active member of the organization.
Organization Slug or ID
Service Agreement ID
One of the supported report types, "devices" or "products"
The start of the date period to query
The end of the date period to query
An optional array of Device IDs
An optional array of Product IDs
$ curl -X POST "https://api.particle.io/v1/orgs/:orgSlugOrId/service_agreements/:serviceAgreementId/usage_reports" \
-H "Authorization: Bearer :access_token" \
-H "Content-Type: application/json" \
-d '{
"report_type": "devices",
"date_period_start": "2022-01-01",
"date_period_end": "2022-01-31",
"devices": ["device1", "device2"]
}'
Usage Report Unique ID
Object type
Usage Report attributes
Usage Report current state
Service Agreement Unique ID
The start of the date period to query
The end of the date period to query
UTC timestamp of when the Usage Report request was created
UTC timestamp of when the Usage Report file expires
Usage Report type
Usage Report parameters
List of Device Unique IDs
List of Product Unique IDs
List of emails to send the report via email
Usage Report file expirable download URL
POST /v1/orgs/:orgSlugOrId/service_agreements/:serviceAgreementId/usage_reports/
HTTP/1.1 202 OK
{
"data": {
"id": "1",
"type": "usage_report",
"attributes": {
"state": "pending",
"service_agreement_id": 1,
"date_period_start": "2022-01-01",
"date_period_end": "2022-01-31",
"created_at": "2022-01-18 13:43:23 -0800",
"expires_at": null,
"report_type": "devices",
"report_params": {
"devices": [
"device1",
"device2"
],
"products": [],
"recipient_list": [
"your@email.com"
]
},
"download_url": null
}
}
GET /v1/user/service_agreements/:serviceAgreementId/notifications
Get user notifications related to a specific service agreement
service_agreements.notifications:list
Service agreement ID
$ curl https://api.particle.io/v1/user/service_agreements/:serviceAgreementId/notifications \
-H "Authorization: Bearer :access_token"
$ curl https://api.particle.io/v1/orgs/:orgSlugOrId/service_agreements/:serviceAgreementId/notifications \
-H "Authorization: Bearer :access_token"
Notification Unique ID
Object type
Notification attributes
indicates the state of the notification
Notification event name
Notification time period
Notification created datetime
Notification updated datetime
Service agreement Id
Notification resource type
Notification details
GET /v1/user/service_agreements/1234/notifications
HTTP/1.1 200 OK
{
"data":[
{
"id": "fff25e4e-7457-4c3c-8f6e-c9d6dfc01110",
"type": "notification",
"attributes": {
"state": "completed",
"event_name": "developer:usage_activity:automatic_unpause",
"time_period": "2022-01-22",
"created_at": "2022-01-22 00:01:00 -0800",
"resource_id": "59",
"resource_type": "ServiceAgreement",
"details": {
"event_type": "automatic_unpause",
"hierarchy_info": {
"name": "automatic_unpause",
"priority": 7
},
"device_pause_date": "2022-01-22T00:01:00.567-08:00",
"next_billing_period_start": "2022-02-22"
}
}
}
]
}