Cloud API reference

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.

Product ID or slug

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.

Format

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.

Postman

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.

Import

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.

Set Environment

Authenticating with Postman

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).

Access Token

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.

Example: List devices

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.

List Devices

You should get output with information about your devices in the bottom pane.

List Output

Example: Calling a function

  • 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.

Function Name
  • You don't need to enter anything in the Authorization tab, but this is how the data gets from the Environment into the API call.
Authorization
  • In this example, we're passing the value on in the arg parameter. This turns on the blue D7 LED on the device with the Blink and LED firmware.
Call function
  • Click Send. It will also show some output in the bottom pane if the device is online and is running the appropriate firmware.

Authentication

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.

How to send your access token

There are three ways to send your access token in a request.

  • In an HTTP Authorization header (always works)
  • Deprecated: In the URL query string (only works with GET requests)
  • Deprecated: In the request body (only works for POST and PUT when body is form encoded)

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://...

Generate an access token

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.

  • Content-Type REQUIRED String

    Must be set to application/x-www-form-urlencoded

  • Authorization REQUIRED String

    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.

  • client_id String

    OAuth client ID. Required if no Authorization header is present.

  • client_secret String

    OAuth client secret. Required if no Authorization header is present.

  • grant_type REQUIRED String

    OAuth grant type. Usually password.

  • username REQUIRED String

    Your Particle account username

  • password REQUIRED String

    Your Particle account password

  • expires_in Number

    How many seconds the token will be valid for. 0 means forever. Short lived tokens are better for security.

  • expires_at Date

    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"
  • access_token String

    The magical token you will use for all the other requests

  • token_type String

    Always set to "Bearer"

  • expires_in String

    The number of seconds this token is valid for. Defaults to 7776000 seconds (90 days) if unspecified in the request. 0 means forever.

  • refresh_token String

    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"
}
  • error String

    The machine readable code identifying the error

  • error_description String

    The human readable reason for the error

  • mfa_token String

    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"
}

List access tokens

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.

  • Authorization REQUIRED String

    Your Particle username and password

  • otp String

    Token given from your MFA device. Usually 6 digits long

$ curl https://api.particle.io/v1/access_tokens \
       -u "joe@example.com:SuperSecret"
  • - Object[]

    List of access tokens

  • -.token String

    Access token

  • -.expires_at String

    Date the token expires and is no longer valid

  • -.client String

    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 an access token

DELETE /v1/access_tokens/:token

Delete your unused or lost tokens.

DEPRECATED. Use the DELETE /v1/access_tokens/current endpoint instead.

  • token REQUIRED String

    Access Token to delete

$ curl -X DELETE https://api.particle.io/v1/access_tokens/123abc \
       -u "joe@example.com:SuperSecret"
  • ok Boolean

    Whether the token was deleted

DELETE /v1/access_tokens/123abc
HTTP/1.1 200 OK
{
  "ok": true
}

Delete all active access tokens

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"
  • ok Boolean

    Whether the tokens were deleted

DELETE /v1/access_tokens
HTTP/1.1 200 OK
{
  "ok": true
}

Delete current access token

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"
  • ok Boolean

    Whether the token was deleted

DELETE /v1/access_tokens/current
HTTP/1.1 200 OK
{
  "ok": true
}

Get the current access token information

GET /v1/access_tokens/current

Get your currently used token.

$ curl https://api.particle.io/v1/access_tokens/current -H "Authorization: Bearer :access_token"
  • expires_in String

    The number of seconds this token is valid for. 0 means forever.

  • client String

    Client program used to create the token.

  • scopes Array

    List of scopes for this token.

  • orgs Array

    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": []
}

OAuth clients

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.

List clients

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
  • productIdOrSlug String

    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"
  • ok Boolean
  • clients Object[]

    An array of OAuth clients

  • clients.id String
  • clients.name String
  • clients.type String
  • clients.redirect_uri String

    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"
        }
    ]
}

Create a client

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
  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • name REQUIRED String

    The name of the OAuth client

  • type REQUIRED String

    web or installed. web is used for the authorization code grant flow similar to Facebook, and Twitter use.

  • redirect_uri String

    Only required for web type. URL that you wish us to redirect to after the OAuth flow.

  • scope String

    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"
  • ok Boolean
  • client Object
  • client.name String
  • client.type String
  • client.id String
  • client.secret String

    Save this! It will never be shown again.

  • client.redirect_uri String

    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"
    }
}

Update a client

PUT /v1/clients/:clientId

Update the name or scope of an existing OAuth client.

  • clients:update
  • clientId REQUIRED String

    The client ID to update

  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • name String

    Give the OAuth client a new name

  • scope String

    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"
  • - Object

    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 a client

DELETE /v1/clients/:clientId

Remove an OAuth client

  • clients:remove
  • clientId REQUIRED String

    The client ID to delete

  • productIdOrSlug String

    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

Errors

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.

API users

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.

Overview - API users

  • An API user can be scoped to an organization or a product.
  • An API user can only have one valid access token associated with it at any one time.
  • If an API user's privileges change - the associated access token will change as well, to prevent scope creep.

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.

Creating an API user

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.


Create an API user scoped to an organization

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.


Create an API user scoped to a product

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"}]}}

Multiple API user scopes

"scopes": [ "devices:list","sims:list" ]

Multiple scopes can be assigned to an API user as follows:

Available API user scopes

  • clients:create
  • clients:list
  • clients:remove
  • clients:update
  • configuration:get
  • configuration:update
  • customers:list
  • customers:remove
  • customers:update
  • devices.diagnostics:get
  • devices.diagnostics:update
  • devices.function:call
  • devices.variable:get
  • devices:get
  • devices:import
  • devices:list
  • devices:ping
  • devices:release
  • devices:remove
  • devices:update
  • events:get
  • events:send
  • firmware.binary:get
  • firmware:create
  • firmware:get
  • firmware:list
  • firmware:release
  • firmware:remove
  • firmware:update
  • groups.impact:get
  • groups:create
  • groups:get
  • groups:list
  • groups:remove
  • groups:update
  • integrations:create
  • integrations:get
  • integrations:list
  • integrations:remove
  • integrations:test
  • integrations:update
  • ledger.definitions:archive
  • ledger.definitions:create
  • ledger.definitions:get
  • ledger.definitions:list
  • ledger.definitions:update
  • ledger.instances.versions:get
  • ledger.instances.versions:list
  • ledger.instances:get
  • ledger.instances:list
  • ledger.instances:remove
  • ledger.instances:set
  • locations:get
  • logic.functions:create
  • logic.functions:execute
  • logic.functions:get
  • logic.functions:list
  • logic.functions:remove
  • logic.functions:update
  • logic.logs:list
  • logic.runs:get
  • logic.runs:list
  • logic.stats:list
  • metrics.events:get
  • metrics.functions:get
  • metrics.integrations:get
  • metrics.online:get
  • metrics.variables:get
  • organization:get
  • products:get
  • products:list
  • service_agreements.notifications:list
  • service_agreements.usage_reports:create
  • service_agreements.usage_reports:get
  • service_agreements:list
  • sims.status:get
  • sims.usage:get
  • sims:get
  • sims:import
  • sims:list
  • sims:remove
  • sims:update
  • teams.users:invite
  • teams.users:list
  • teams.users:remove
  • teams.users:update

Determining API user scopes

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.

Updating an API user

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.

Listing API users

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
    }
  ]
}

Deleting an API user

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:

Errors - API users

{"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:

API rate limits

The following API rate limits apply. Exceeding the rate limit will result in a 429 HTTP error response.

All API functions - API rate limits

  • Maximum of 10,000 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • Can be increased for enterprise customers
  • All API Routes

Create an access token - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • Can be increased for enterprise customers
  • API Route: POST /oauth/token

List access tokens - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • API Route: GET /v1/access_tokens

Delete an access token - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • API Route: DELETE /v1/access_tokens/:token

Create a user account - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • API Route: POST /v1/users

Delete user account - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • API Route: DELETE /v1/user

Generate a password reset token - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • API Route: POST /v1/user/password-reset

Reset password - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • API Route: PUT /v1/user/password-reset

Get all events - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • Can be increased for enterprise customers
  • API Route: GET /v1/events

Subscribe to server-sent events - API rate limits

  • Maximum of 100 requests every 5 minutes
  • Limited by source IP address (public IP address)
  • Can be increased for enterprise customers
  • API Routes:
    • GET /v1/devices/events/
    • GET /v1/devices/:DeviceID/events/
    • GET /v1/orgs/:OrgID/events/
    • GET /v1/orgs/:OrgID/devices/:DeviceID/events/
    • GET /v1/orgs/products/:ProductID/events/
    • GET /v1/products/:ProductID/events/
    • GET /v1/products/:ProductID/devices/:DeviceID/events/

Open server-sent event streams - API rate limits

  • A maximum of 100 simultaneous connections
  • Limited by source IP address (public IP address)

Get device data via serial number - API rate limits

  • Maximum of of 50 requests every hour
  • Limited per user account that generated the access token
  • Can be increased for enterprise customers
  • API Route: GET /v1/serial_numbers/:SerialNumber

Beware of monitoring variables for change

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.

Make sure you handle error conditions properly

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.

Versioning

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.

Devices

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.

List devices

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"
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"
  }
]

List devices in a product

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • deviceId String

    Filter results to devices with this ID (partial matching)

  • groups String

    Comma separated list of full group names to filter results to devices belonging to these groups only

  • deviceName String

    Filter results to devices with this name (partial matching)

  • serialNumber String

    Filter results to devices with this serial number (partial matching)

  • sortAttr String

    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

  • sortDir String

    The direction of sorting. Pass asc for ascending sorting or desc for descending sorting

  • quarantined true

    include / exclude quarantined devices

  • page Number

    Current page of results

  • perPage Number

    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"
  • devices Object[]

    An array of devices objects. See Get device information for the response attributes of each device.

  • customers Object[]

    An array of customer objects

  • customers.id String

    Customer ID

  • customers.username String

    Customer username

  • meta Object

    Pagination metadata

  • meta.total_pages Number

    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
    }
}

Import devices into product

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • id String

    A device ID to import into a product. Pass id if you are trying to import a single device

  • ids String[]

    An array of device ID to import into a product. Pass ids if you are trying to import multiple device

  • import_sims Boolean

    Import SIM card associated with each device into the product

  • claim_user String

    The username (email) of a Particle user to claim the imported devices. This user must be a member of the product team.

  • file File

    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" }'
  • updated Number

    The number of devices successfully added to the product

  • updatedDeviceIds Array

    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.

  • existingDeviceIds Array

    Device identifiers that were already in the product

  • nonmemberDeviceIds Array

    Device identifiers that belong to another owner and could not be imported

  • invalidDeviceIds Array

    Device identifiers that were invalid and could not be imported

  • protectedDeviceIds Array

    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 device information

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.

  • deviceId REQUIRED String

    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"
  • id String

    Device ID

  • name String

    Device name

  • owner String

    Particle username for the user who claimed this device

  • last_ip_address String

    IP address of the device the last time it connected to the cloud

  • last_heard Date

    Date and Time that the cloud last heard from the device in ISO 8601 format

  • last_handshake_at Date

    Date and time that the device most recently connected to the cloud in ISO 8601 format

  • product_id Number

    For development devices, this equals platform_id. For product devices, your product number.

  • online Boolean

    Indicates whether the device is currently connected to the cloud

  • connected Boolean

    Deprecated. Use online

  • platform_id Number

    Indicates the type of device. Example values are 6 for Photon, 10 for Electron, 12 for Argon, 13 for Boron.

  • cellular Boolean

    True for cellular devices (Electron, Boron), false otherwise

  • notes String

    Free-form notes about the device

  • functions String[]

    List of function names exposed by the device

  • variables Object

    List of variable name and types exposed by the device

  • serial_number String

    The serial number of the device, if it exists

  • status String

    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.

  • iccid String

    Last SIM card ID used for cellular devices

  • last_iccid String

    Deprecated. Use iccid.

  • imei String

    IMEI number for cellular devices

  • mac_wifi String

    The device MAC address if it has one. Non cellular devices only

  • system_firmware_version String

    Version of Device OS running on the device last reported to the cloud

  • current_build_target String

    Deprecated. Use system_firmware_version.

  • pinned_build_target String

    Version of Device OS to use when compiling firmware for this device in the Web IDE. If not set, uses default_build_target.

  • default_build_target String

    Version of Device OS to use when compiling firmware for the platform of this device in the Web IDE.

  • firmware_updates_enabled Boolean

    Indicates whether the device will accept firmware updates without being forced

  • firmware_updates_forced Boolean

    Indicates whether firmware updates on the device have been forced from the cloud.

  • mobile_secret String

    The shared secret used by a mobile app to communicate securely with a device over BLE during setup

  • firmware_product_id Number

    The product ID that the device reported in its firmware the last time it connected to the cloud. Product devices only

  • groups Object[]

    An array of group names that the device belongs to. Product devices only

  • firmware_version Number

    The version number the device reported in its firmware. Product devices only

  • desired_firmware_version Number

    The version of firmware that the device has been individually locked to run. Product devices only

  • targeted_firmware_release_version Number

    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

  • development Boolean

    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

  • quarantined Boolean

    If set to true, the device is unrecognized and has lost product privileges until it is manually approved. Product endpoint only

  • denied Boolean

    If set to true, this is a quarantined device that has been permanently denied access to product privileges. Product endpoint only

  • device_protection.status String

    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 product device information

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
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug REQUIRED String

    Product ID or Slug

Get a variable value

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
  • deviceId REQUIRED String

    Device ID

  • varName REQUIRED String

    Variable name

  • productIdOrSlug String

    Product ID or Slug. Product endpoint only.

  • format "raw"

    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"
  • result String

    The variable value

  • name String

    The variable name

  • coreInfo Object

    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

Call a function

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
  • deviceId REQUIRED String
  • functionName REQUIRED String
  • productIdOrSlug String

    Product ID or Slug. Product endpoint only.

  • arg String

    Function argument with a maximum length of 63 characters

  • format "raw"

    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"
  • id String

    Device ID

  • name String

    Device name

  • connected Boolean

    Indicates if the device is currently connected to the cloud

  • return_value Number

    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

Ping a device

PUT /v1/devices/:deviceId/ping

This will ping a device, enabling you to see if your device is online or offline

  • devices:ping
  • deviceId REQUIRED String
  • productIdOrSlug String

    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"
  • online Boolean

    Indicates if the device is currently online

PUT /v1/devices/0123456789abcdef01234567/ping
HTTP/1.1 200 OK
{
  "online": true,
  "ok": true
}

Rename a device

PUT /v1/devices/:deviceId

Rename a device, either owned by a user or a product

  • devices:update
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug String

    Product ID or slug. Product endpoint only

  • name REQUIRED String

    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"
  • id String

    Device ID

  • name String

    Device name

  • updated_at Date

    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"
}

Add device notes

PUT /v1/devices/:deviceId
  • devices:update
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug String

    Product ID or slug. Product endpoint only

  • notes REQUIRED String

    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"
  • id String

    Device ID

  • notes String

    Notes that have been added to the device

  • updated_at Date

    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"
}

Claim a device

POST /v1/devices

Claim a new or unclaimed device to your account.

  • id REQUIRED String

    Device ID

  • request_transfer REQUIRED true

    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"
  • transfer_id String

    Unique ID that represents the transfer

Remove device from product

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • deviceId REQUIRED String

    ID of the device to be removed

DELETE /v1/products/photon/devices/123abc
HTTP/1.1 204 NO CONTENT

Unclaim device

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
  • deviceId REQUIRED String

    ID of the device to be unclaimed

  • productIdOrSlug String

    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
}

Signal a device

PUT /v1/devices/:deviceId

Make the device conspicuous by causing its LED to flash in rainbow patterns

  • deviceId REQUIRED String

    Device ID

  • signal REQUIRED Number

    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
}

Force enable OTA updates

PUT /v1/devices/:deviceId

Force enable OTA updates on this device.

  • devices:update
  • deviceId REQUIRED String

    Device ID

  • firmware_updates_forced REQUIRED Boolean

    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
}

Look up device identification from a serial number

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.

  • serial_number REQUIRED String

    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"
  • deviceID String

    The ID of the device associated with this device

  • iccid String

    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"
}

Remote diagnostics

Refresh device vitals

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.

  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug String

    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
}

Device vitals event

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
  • - Object

    The device vitals payload information

  • -.device Object

    Device vitals data containing diagnostics reported directly from the device

  • -.device.network Object

    Represents diagnostics on all layers of the network stack that impact the device's ability to communicate with the Device Cloud

  • -.device.network.cellular Object

    Cellular network information

  • -.device.network.cellular.radio_access_technology String

    The human readible form of the access technology. Possible values are 2G, 3G, LTE

  • -.device.network.cellular.operator String

    The name of the company operating the tower on which the device is currently connected

  • -.device.network.cellular.cell_global_identity Object

    A globally unique identifier that can be used to geographically locate the tower to which a device is connected

  • -.device.network.cellular.cell_global_identity.mobile_country_code Number

    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)

  • -.device.network.cellular.cell_global_identity.mobile_network_code String

    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

  • -.device.network.cellular.cell_global_identity.location_area_code Number

    a unique number identifying the current location area. A location area is a set of base stations that are grouped together to optimize signalling

  • -.device.network.cellular.cell_global_identity.cell_id Number

    a generally unique number used to identify each Base Transceiver Station (BTS) or sector of a BTS within a location area code

  • -.device.network.signal Object

    The signal strength and quality metrics

  • -.device.network.signal.at String

    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

  • -.device.network.signal.strength Number

    Measure of the current radio network strength in % (0-100)

  • -.device.network.signal.strength_units String

    Always %

  • -.device.network.signal.strengthv Number

    Signal strength raw value specific to the access technology

  • -.device.network.signal.strengthv_units String

    Always dbM

  • -.device.network.signal.strengthv_type String

    The algorithm used to calculate signal strength. Possible values are RSSI (Wi-Fi), RXLEV (2G), RSCP (3G), RSRP (LTE)

  • -.device.network.signal.quality Number

    Measure of the current radio connection quality in % (0-100)

  • -.device.network.signal.quality_units String

    Always %

  • -.device.network.signal.qualityv Number

    Signal quality raw value specific to the access technology

  • -.device.network.signal.qualityv_units String

    Always dB

  • -.device.network.signal.qualityv_type String

    The algorithm used to calculate signal quality. Possible values are SNR (Wi-Fi), RXQUAL (2G), ECN0 (3G), RSRQ (LTE)

  • -.device.network.connection Object

    Statistics about the network

  • -.device.network.connection.status String

    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

  • -.device.network.connection.error Number

    A platform-specific error code that is returned by the low-level Device OS function for the most recent network connectivity event

  • -.device.network.connection.disconnects Number

    Count of network disconnects

  • -.device.network.connection.attempts Number

    Number of attempts required to establish a successful network connection

  • -.device.network.connection.disconnect_reason String

    Last reason the network got disconnected. Possible values are none, error, user, network_off, listening, sleep, reset

  • -.device.cloud Object

    Device Cloud communication information

  • -.device.cloud.connection Object

    Information on the state of the device's cloud connection

  • -.device.cloud.connection.status String

    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

  • -.device.cloud.connection.error Number

    A platform-specific error code that is returned by the low-level Device OS function for the most recent cloud connectivity event

  • -.device.cloud.connection.attempts Number

    Number of attempts required to establish a successful cloud connection

  • -.device.cloud.disconnects Number

    The number of unexpected disconnections from the cloud since the last reset

  • -.device.cloud.connection.disconnect_reason String

    Last reason the cloud connection got disconnected. Possible values are none, error, user, network_disconnect, listening

  • -.device.cloud.coap Object

    Information regarding the underlying communication protocol

  • -.device.cloud.coap.transmit Number

    The number of CoAP messages sent by the device to the cloud

  • -.device.cloud.coap.retransmit Number

    The number of times a CoAP message was resent by the device to the cloud due to the original message not being acknowledged

  • -.device.cloud.coap.unack Number

    The number of CoAP messages that were resent the maximum number of times by the device, still not acknowledged by the cloud then dropped

  • -.device.cloud.coap.round_trip Number

    The round-trip time of the last device to cloud message in milliseconds

  • -.device.cloud.publish Object

    Information regarding publish attempts from the device

  • -.device.cloud.publish.rate_limited Number

    The current count of rate limited publishes since the device was reset

  • -.device.power Object

    Concerns sources of device power. This will only be populated for devices with on-board power management.

  • -.device.power.battery Object

    Information about batteries

  • -.device.power.battery.charge Number

    Battery charge as a percent

  • -.device.power.battery.state String

    The current charging state of the battery. Possible values are unknown, not_charging, charging, charged, discharging, fault, disconnected

  • -.device.power.source String

    An enumeration describing the current power source. Possible values are unknown, VIN, USB host, USB adapter, USB otg

  • -.device.system Object

    Indicators of general device health and system status

  • -.device.system.uptime Number

    The number of seconds the system has been running

  • -.device.system.memory Object

    Memory metrics for the device

  • -.device.system.memory.used Number

    User application static RAM + heap used

  • -.device.system.memory.total Number

    Total amount of RAM available on the device in bytes

  • -.service Object

    Device vitals data containing diagnostics collected by the Particle Device Cloud on behalf of the device

  • -.service.device Object

    Cloud to device information

  • -.service.device.status String

    The result of the last attempt to decode the vitals message from the device. Should always be ok. Possible values are ok, error

  • -.service.cloud Object

    Information on the device's cloud session

  • -.service.cloud.uptime Number

    Duration of the device session in seconds

  • -.service.cloud.publish Object

    Cloud-side metrics for device messages

  • -.service.cloud.publish.sent Number

    The total number of Particle.publish events sent by the device

  • -.service.coap Object

    Information regarding the underlying communication protocol

  • -.service.coap.round_trip Number

    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 last known device vitals

GET /v1/diagnostics/:deviceId/last

Returns the last device vitals payload sent by the device to the Device Cloud.

  • devices.diagnostics:get
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug String

    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"
  • diagnostics Object

    The last known device vitals object

  • diagnostics.updated_at Date

    Timestamp of when the diagnostic vitals record was reported

  • diagnostics.deviceID String

    ID of the device

  • diagnostics.payload Object

    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 all historical device vitals

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.

  • Accept String

    Optionally set to text/csv to return historic device vitals as a CSV

  • devices.diagnostics:get
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug String

    Product ID or slug. Product endpoint only

  • start_date Date

    Oldest diagnostic to return, inclusive. Date in ISO8601 format.

  • end_date Date

    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"
  • diagnostics Object[]

    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.
                }
            },
            ...
        ]
 }
  • bad_request Object

    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 cellular network status

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
  • iccid REQUIRED String

    The ICCID of the desired SIM

  • productIdOrSlug String

    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"
  • ok Boolean

    Whether the request was successful

  • meta Object

    Meta information about the task

  • meta.created_at String

    UTC timestamp of when the task was kicked off

  • meta.expires_at String

    UTC timestamp when the task results will expire

  • meta.check_again_after String

    UTC timestamp of the suggested time after which to check status again

  • meta.method String

    Set to async to communicate an asynchronous request

  • meta.state String

    the state of the task. Can be pending or complete.

  • meta.task_id String

    the id of the task

  • sim_status Object

    Status information about the SIM

  • sim_status.connected Boolean

    Whether the device/SIM has an active data session with a cell tower (both GSM and data connection are true)?

  • sim_status.gsm_connection Boolean

    Whether the device/SIM has a GSM connection?

  • sim_status.data_connection Boolean

    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,
    }
}

User

Get user

GET /user

Return the user resource for the currently authenticated user.

$ curl https://api.particle.io/v1/user -H "Authorization: Bearer :access_token"
  • username String

    Email address for current user

  • subscription_ids Array

    Subscriptions for SIM cards and products

  • mfa Object

    Includes whether MFA is enabled

  • account_info Object

    An object that contains a first_name, last_name, and business_account

  • wifi_device_count Integer

    Number of devices that count against the Wi-Fi device cap

  • cellular_device_count Integer

    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
}

Update user

PUT /user

Update the logged-in user. Allows changing email, password and other account information.

  • password REQUIRED String

    The new password

  • username REQUIRED String

    The new account email address

  • account_info REQUIRED Object

    The new account info

  • current_password REQUIRED String

    The current password. Required to change username or password

  • invalidate_tokens REQUIRED Boolean

    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."
}

Delete user

PUT /user

Delete the logged-in user. Allows removing user account and artifacts from Particle system

  • password REQUIRED String

    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."
}

Forgot password

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.

  • username REQUIRED String
$ 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."
}

Quarantine

Approve a quarantined device

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • id REQUIRED String

    ID of the device to be denied

POST /v1/products/photon/devices
{ "id": "123abc" }
HTTP/1.1 200 OK

Deny a quarantined device

DELETE /v1/products/:productIdOrSlug/devices/:deviceId

Deny a quarantined device

  • devices:remove
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • deviceId REQUIRED String

    ID of the device to be denied

  • deny REQUIRED true

    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

SIM cards

List SIM cards

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
  • productIdOrSlug String

    Product ID or slug. Product endpoint only

  • iccid String

    Filter results to SIMs with this ICCID (partial matching)

  • deviceId String

    Filter results to SIMs with this associated device ID (partial matching)

  • deviceName String

    Filter results to SIMs with this associated device name (partial matching)

  • page Number

    Current page of results

  • perPage Number

    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"
  • sims Object[]

    An array of SIM card objects

  • sims._id String

    ICCID of the SIM

  • sims.activations_count Number

    Number of times the SIM has been activated

  • sims.base_country_code String

    The ISO Alpha-2 code of the country where the SIM card is based

  • sims.base_monthly_rate Number

    The monthly rate of the 1 MB data plan for this SIM card, in cents

  • sims.deactivations_count Number

    Number of times the SIM has been deactivated

  • sims.first_activated_on Date

    Timestamp of the first activation date of the SIM card

  • sims.last_activated_on Date

    Timestamp of the last activation date of the SIM card

  • sims.last_activated_via String

    The method used to activate the SIM card. Internal use only, will be deprecated

  • sims.last_status_change_action String

    The last state change of the SIM card

  • sims.last_status_change_action_error String

    Whether the last action change resulted in an error. Set to "yes" or "no"

  • sims.msisdn String

    MSISDN number of the Ublox modem

  • sims.overage_monthly_rate Number

    The per-MB overage rate for this SIM card, in cents

  • sims.status String

    The current connectivity status of the SIM card

  • sims.stripe_plan_slug String

    Data plan type. Internal use only, will be deprecated

  • sims.updated_at Date

    Timestamp representing the last time the SIM was updated

  • sims.user_id String

    The ID of the user who owns the SIM card

  • sims.product_id String

    The ID of the product who owns the SIM card

  • sims.carrier String

    The Telefony provider for the SIM card's connectivity

  • sims.last_device_id String

    The device ID of the SIM card's last associated device

  • sims.last_device_name String

    The device name of the SIM card's last associated device

  • meta Object

    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 SIM information

GET /v1/sims/:iccid

Retrieve a SIM card owned by an individual or a product.

  • sims:get
  • iccid String

    Filter results to SIMs with this ICCID (partial matching) Product endpoint only

  • productIdOrSlug String

    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"
  • sim Object

    The SIM card data object

  • sim._id String

    ICCID of the SIM

  • sim.activations_count Number

    Number of times the SIM has been activated

  • sim.base_country_code String

    The ISO Alpha-2 code of the country where the SIM card is based

  • sim.base_monthly_rate Number

    The monthly rate of the 1 MB data plan for this SIM card, in cents

  • sim.deactivations_count Number

    Number of times the SIM has been deactivated

  • sim.first_activated_on Date

    Timestamp of the first activation date of the SIM card

  • sim.last_activated_on Date

    Timestamp of the last activation date of the SIM card

  • sim.last_activated_via String

    The method used to activate the SIM card. Internal use only, will be deprecated

  • sim.last_status_change_action String

    The last state change of the SIM card

  • sim.last_status_change_action_error String

    Whether the last action change resulted in an error. Set to "yes" or "no"

  • sim.msisdn String

    MSISDN number of the Ublox modem

  • sim.overage_monthly_rate Number

    The per-MB overage rate for this SIM card, in cents

  • sim.status String

    The current connectivity status of the SIM card

  • sim.stripe_plan_slug String

    Data plan type. Internal use only, will be deprecated

  • sim.updated_at Date

    Timestamp representing the last time the SIM was updated

  • sim.user_id String

    The ID of the user who owns the SIM card

  • sim.product_id String

    The ID of the product who owns the SIM card

  • sim.carrier String

    The Telefony provider for the SIM card's connectivity

  • sim.last_device_id String

    The device ID of the SIM card's last associated device

  • sim.last_device_name String

    The device name of the SIM card's last associated device

  • sim.owner String

    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 data usage

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.

  • iccid REQUIRED String

    The ICCID of the desired SIM

  • productIdOrSlug String

    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 String

    ICCID of the SIM

  • usage_by_day Object[]

    An array of data usage by day

  • usage_by_day.date String

    The date of the usage day

  • usage_by_day.mbs_used Number

    Megabytes used in the usage day

  • usage_by_day.mbs_used_cumulative Number

    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 data usage for product fleet

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
  • productIdOrSlug REQUIRED String

    Product ID or slug

$ curl https://api.particle.io/v1/products/:productIdOrSlug/sims/data_usage \
       -H "Authorization: Bearer :access_token"
  • total_mbs_used Number

    The total number of megabytes consumed by the fleet in the current billing period

  • total_active_sim_cards Number

    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.

  • usage_by_day Object[]

    An array of data usage by day

  • usage_by_day.date String

    The date of the usage day

  • usage_by_day.mbs_used Number

    Megabytes used in the usage day

  • usage_by_day.mbs_used_cumulative Number

    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
        },
        ...
    ]
}

Activate SIM

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.

  • iccid REQUIRED String

    The ICCID of the SIM to update

  • action REQUIRED String

    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

Import and activate product SIMs

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
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • sims String[]

    An array of SIM ICCIDs to import

  • file File

    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
}

Deactivate SIM

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
  • iccid REQUIRED String

    The ICCID of the SIM to update

  • productIdOrSlug String

    Product ID or slug. Product endpoint only

  • action REQUIRED String

    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

Reactivate SIM

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
  • iccid REQUIRED String

    The ICCID of the SIM to update

  • productIdOrSlug String

    Product ID or slug. Product endpoint only

  • action REQUIRED String

    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

Release SIM from account

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
  • iccid REQUIRED String

    The ICCID of the desired SIM

  • productIdOrSlug String

    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

Events

Get a stream of events

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.

  • eventPrefix REQUIRED String

    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 String

    event name

  • data String

    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 a stream of your events

GET /v1/devices/events/:eventPrefix

Open a stream of Server Sent Events for all events for your devices.

  • eventPrefix String

    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 String

    event name

  • data String

    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 a stream of events for a device

GET /v1/devices/:deviceId/events/:eventPrefix

Open a stream of Server Sent Events for all events for the specified device.

  • deviceId REQUIRED String

    Device ID

  • eventPrefix String

    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 String

    event name

  • data String

    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"}

Product event stream

GET /v1/products/:productIdOrSlug/events/:eventPrefix

Open a stream of Server Sent Events for all events for a product.

  • events:get
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • eventPrefix String

    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 String

    event name

  • data String

    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"}

Publish an event

POST /v1/devices/events

Publish an event

  • name REQUIRED String

    Event name

  • data String

    Event data

  • ttl Number

    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
}

Publish a product event

POST /v1/products/:productIdOrSlug/events

Publish an event that is sent to the product's event stream

  • events:send
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • name REQUIRED String

    Event name

  • data String

    Event data

  • ttl Number

    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:

  • Publishes are not end-to-end confirmed. Even if the Particle.publish returns true, there is no guarantee that any recipient (another device, webhook, or SSE) will receive it.
  • It is possible to receive an event more than once. The most common reason is a lost ACK, which will cause the device to send the event again. Storing a unique identifier in the event payload may help code defensively for this possibility.
  • It is possible that events will arrive out-of-order. The most common cause is retransmission, but it can also occur because events can flow through different redundant servers, each with slightly difference latency, so it's possible that two event sent rapidly will arrive out-of-order as well. This is common for multi-part webhook responses.
  • It is possible that even if 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:

  • Works for developer and product event streams.
  • Can get all events, or a subset of events by prefix filter.
  • Works from a network behind a firewall or NAT typically with no changes required (no port forwarding required).
  • You do not need TLS/SSL server certificates for encrypted communication, because the connection is outbound.
  • You do not need separate authentication; Particle API tokens are used for authentication.
  • It's efficient - the connection only needs to be established and authenticated once.

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:

  • You can only have one server accepting events with SSE. With webhooks you can have multiple servers behind a load balancer for both server redundancy as well as load sharing.
  • If the SSE stream fails for any reason, you could end up losing events. It can take up to a minute to detect that this has happened in some cases.
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:

  • The connection can be closed at any time by the SSE server. You must be able to handle this and reconnect.
  • The connection can stop receiving data because the TCP connection is losing all packets when crossing the Internet. You can detect this because the SSE client will not get any events or the 60 second ping, and it should try reconnecting. This also means that you could lose up to 60 seconds of events in the case of an Internet outage.
  • Beware of excessively reconnecting and rate limits.

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.

Integrations [Webhooks]

Create a webhook

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
  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • integration_type REQUIRED String

    Must be set to Webhook

  • event REQUIRED String

    The name of the Particle event that should trigger the webhook

  • url REQUIRED String

    The web address that will be targeted when the webhook is triggered

  • name String

    A human-readable description of the webhook. Defaults to "{event} for {domain}" if omitted.

  • requestType REQUIRED String

    Type of web request triggered by the webhook that can be set to GET, POST, PUT, or DELETE

  • deviceID String

    Limits the webhook triggering to a single device

  • body String

    Send a custom body along with the HTTP request

  • json Object

    Send custom data as JSON with the request. This will change the Content-Type header of the request to application/json

  • form Object

    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

  • query Object

    Send query parameters in the URL of the request by including key/value pairs

  • auth Object

    Add an HTTP basic auth header by including a JSON object with username/password set

  • headers Object

    Add custom HTTP headers by including key/value pairs

  • responseTopic String

    Customize the webhook response event name that your devices can subscribe to

  • errorResponseTopic String

    Customize the webhook error response event name that your devices can subscribe to

  • responseTemplate String

    Customize the webhook response body that your devices can subscribe to

  • noDefaults Boolean

    Set to true to not add the triggering Particle event's data to the webhook request

  • disabled Boolean

    Set to true to stop events from being sent to this webhook

  • rejectUnauthorized Boolean

    Set to false to skip SSL certificate validation of the target URL

  • template String

    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"
  • ok Boolean
  • id String

    Webhook ID

  • url String

    Web address that will be targeted when the webhook is triggered

  • created_at String

    Timestamp of when the webhook was created

  • integration_type String

    Should be set to Webhook

  • hookUrl String

    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"
 }

Enable Azure IoT Hub integration

POST /v1/integrations

Enable an integration with Azure IoT Hub. For more details, check out the tutorial.

  • integrations:create
  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • integration_type REQUIRED String

    Must be set to AzureIotHub

  • event REQUIRED String

    The name of the Particle event that should trigger the integration

  • hub_name REQUIRED String

    The name of your Azure IoT Hub

  • name String

    A human-readable description of the webhook. Defaults to "{event} for {hub_name}" if omitted.

  • policy_name REQUIRED String

    The name of the shared access policy used for authentication

  • policy_key REQUIRED String

    The shared access policy key used for authentication

  • deviceID String

    Limits the integration triggering to a single device

  • json Object

    A custom JSON payload to send along with the request

  • disabled Boolean

    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"
  • ok Boolean
  • id String

    Integration ID

  • created_at String

    Timestamp of when the integration was created

  • integration_type String

    Should be set to AzureIotHub

  • integrationUrl String

    URL to fetch information about the integration

  • hub_name String

    The name of your Azure IoT Hub

  • policy_name String

    The name of the shared access policy used for authentication

  • policy_key String

    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"
}

Enable Google Cloud Platform integration

POST /v1/integrations

Enable an integration with Google Cloud Platform. For more details, check out the tutorial.

  • integrations:create
  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • integration_type REQUIRED String

    Must be set to GoogleCloudPubSub

  • event REQUIRED String

    The name of the Particle event that should trigger the integration

  • topic REQUIRED String

    The Google Cloud Pub Sub topic name for publishing messages

  • name String

    A human-readable description of the webhook. Defaults to "{event} for {topic}" if omitted.

  • deviceID String

    Limits the integration triggering to a single device

  • disabled Boolean

    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"
  • ok Boolean
  • id String

    Integration ID

  • created_at String

    Timestamp of when the integration was created

  • integration_type String

    Should be set to GoogleCloudPubSub

  • integrationUrl String

    URL to fetch information about the integration

  • topic String

    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"
}

Enable Google Maps integration

POST /v1/integrations

Enable an integration with Google Maps. For more details, check out the tutorial.

  • integrations:create
  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • integration_type REQUIRED String

    Must be set to GoogleMaps

  • event REQUIRED String

    The name of the Particle event that should trigger the integration

  • name String

    A human-readable description of the webhook. Defaults to "{event} for Google Maps" if omitted.

  • api_key REQUIRED String

    Your Google Maps Geolocation API key. Check out these docs for details

  • deviceID String

    Limits the integration triggering to a single device

  • disabled Boolean

    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"
  • ok Boolean
  • id String

    Integration ID

  • created_at String

    Timestamp of when the integration was created

  • api_key String

    Your Google Maps Geolocation API key

  • integration_type String

    Should be set to GoogleCloudPubSub

  • integrationUrl String

    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"
}

Edit a Webhook

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
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • event String

    The name of the Particle event that should trigger the webhook

  • deviceID String

    Limits the webhook triggering to a single device

  • url String

    The web address that will be targeted when the webhook is triggered

  • name String

    A human-readable description of the webhook

  • requestType String

    Type of web request triggered by the webhook that can be set to GET, POST, PUT, or DELETE

  • body String

    Send a custom body along with the HTTP request

  • json Object

    Send custom data as JSON with the request. This will change the Content-Type header of the request to application/json

  • form Object

    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

  • query Object

    Send query parameters in the URL of the request by including key/value pairs

  • auth Object

    Add an HTTP basic auth header by including a JSON object with username/password set

  • headers Object

    Add custom HTTP headers by including key/value pairs

  • responseTopic String

    Customize the webhook response event name that your devices can subscribe to

  • errorResponseTopic String

    Customize the webhook error response event name that your devices can subscribe to

  • responseTemplate String

    Customize the webhook response body that your devices can subscribe to

  • noDefaults Boolean

    Set to true to not add the triggering Particle event's data to the webhook request

  • disabled Boolean

    Set to true to stop events from being sent to this webhook

  • rejectUnauthorized Boolean

    Set to false to skip SSL certificate validation of the target URL

  • template String

    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"
  • integration Object

    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"
    }
}

Edit Azure IoT Hub Integration

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
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • event String

    The name of the Particle event that should trigger the integration

  • name String

    A human-readable description of the webhook

  • deviceID String

    Limits the integration triggering to a single device

  • hub_name String

    The name of your Azure IoT Hub

  • policy_name String

    The name of the shared access policy used for authentication

  • policy_key String

    The shared access policy key used for authentication

  • json Object

    A custom JSON payload to send along with the request

  • disabled Boolean

    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"
  • integration Object

    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"
    }
}

Edit Google Cloud Platform Integration

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
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • event String

    The name of the Particle event that should trigger the integration

  • name String

    A human-readable description of the webhook

  • deviceID String

    Limits the integration triggering to a single device

  • topic String

    The Google Cloud Pub Sub topic name for publishing messages

  • disabled Boolean

    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"
  • integration Object

    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"
    }
}

Edit Google Maps Integration

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
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • event String

    The name of the Particle event that should trigger the integration

  • name String

    A human-readable description of the webhook

  • deviceID String

    Limits the integration triggering to a single device

  • api_key String

    Your Google Maps Geolocation API key. Check out these docs for details

  • disabled Boolean

    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"
  • integration Object

    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 integration

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
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    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"
  • integration Object

    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.

  • integration.logs Object[]

    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"
    }
}

List integrations

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
  • productIdOrSlug String

    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"
  • - Object[]

    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"
    }
]

Test an integration

POST /v1/integrations/:integrationId/test

Send a test event that triggers the integration. Helps build confidence that an integration is configured properly.

  • integrations:test
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    Product ID or slug. Product endpoint only.

  • data String

    Custom data to send with the test event. Defaults to "test-event" if omitted.

  • device_id String

    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"
  • pass Boolean

    Whether the integration was able to receive a successful response from the target

  • data String

    The data returned by a successful integration test attempt

  • error String

    If unsuccessful, the error returned from the target

POST /v1/integrations/1234/test
HTTP/1.1 200 OK
{
      pass: true,
      data: null
}

Delete an integration

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
  • integrationId REQUIRED String

    The ID of the desired integration

  • productIdOrSlug String

    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

Special events

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.

Special device events

Connection status

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.

Safe-mode

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.

Flashing

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"}

app-hash

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"}

particle/device/updates

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.

spark/device/last_reset

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 reset reason is not one of these known codes, the numeric value is included.
  • Not all hardware platforms can generate all reset reasons.

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.

Future reserved events

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 }

Special webhook events

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:

  • hook-response/name_of_my_event/0
  • hook-response/name_of_my_event/1
  • hook-response/name_of_my_event/2
  • ...

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.

Webhook events and the product event stream

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.

Asset tracking events

Tracker location events

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.

cmd

This currently always the string loc, indicating that the payload contains the loc object.

time

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.

loc.lck

Lock or fix status. If 0, the GNSS has not locked yet. If non-zero, it has locked and the lat/lon are valid.

loc.time

GNSS timestamp. This may be different than the device and cloud times.

loc.lat

Latitude part of geographic coordinate in reference to WGS84 datum. It is floating point degrees in the range of -180.0 to +180.0.

loc.lon

Longitude part of geographic coordinate in reference to WGS84 datum. It is floating point degrees in the range of -90.0 to +90.0.

loc.alt

Altitude, in meters, part of geographic coordinate in reference to WGS84 datum.

loc.hd

Heading, in degrees, of perceived direction. It is floating point degrees in the range of -360.0 to +360.0.

loc.h_acc

Horizontal accuracy, in meters, of geographic latitude and longitude coordinates.

loc.v_acc

Vertical accuracy, in meters, of geographic altitude coordinates.

loc.spd

Speed, in meters per second, of perceived GNSS movement. Added in Tracker Edge v12.

loc.batt

Battery level, in percentage (0-100.0) when available and valid. This field will be omitted when no battery is connected.

loc.cell

Cellular signal strength/quality, in percentage (0-100.0).

loc.temp

Device temperature, in degrees Celsius, if available.

towers.str

Serving and neighboring cell tower signal strength (RSSI in dBm). Added in Tracker Edge v12.

towers.rat

Radio Access Technology, for example, "lte". Added in Tracker Edge v12.

towers.mcc

Mobile Country Code (0 - 999). Added in Tracker Edge v12.

towers.mnc

Mobile Network Code (0 - 999). This is the operator or carrier within the country. Added in Tracker Edge v12.

towers.lac

Location Area Code (0 - 65535). Added in Tracker Edge v12.

towers.cid

Cell Identifier (0 - 268435455). Added in Tracker Edge v12.

towers.nid

Neighboring tower Physical Cell ID (0 - 2147483647). Added in Tracker Edge v12.

towers.ch

Frequency channel number (0 - 2147483647). Added in Tracker Edge v12.

wps.bssid

MAC address (BSSID) for the base station (access point). Added in Tracker Edge v12.

wps.str

Signal strength (RSSI in dBm). Added in Tracker Edge v12.

wps.ch

Wi-Fi channel number. Added in Tracker Edge v12.

trig

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 motion
  • imu_g IMU wake on high-G acceleration (4g for at least 2.5ms.)
  • temp_h High temperature wake
  • temp_l Low temperature wake
  • user User-triggered publish
  • batt_warn Low battery warning
  • batt_low Low battery
  • outside1 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

req_id

The request identifier, used to make sure the event was received.

Enhanced location events

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.

loc.src

The sources used for enhanced geolocation, an array. Can be "cell" or "wifi" or both. Added in Tracker Edge v12.

Location point schema

The full JSON schema for the location point can be downloaded here.

Firmware

Flash a device with source code

PUT /v1/devices/:deviceId

Update the device firmware from source

  • deviceId REQUIRED String

    Device ID

  • file REQUIRED String

    The source code encoded in multipart/form-data format

  • build_target_version String

    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"
}

Flash a device with a pre-compiled binary

PUT /v1/devices/:deviceId

Update the device firmware from a binary

  • deviceId REQUIRED String

    Device ID

  • file REQUIRED String

    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"
}

Flash a device with a bundle

PUT /v1/devices/:deviceId

Update the device firmware from a bundle

  • deviceId REQUIRED String

    Device ID

  • file REQUIRED String

    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"
}

Compile source code

POST /v1/binaries

Compile source code into a binary for a device

  • file REQUIRED String

    The source code encoded in multipart/form-data format

  • platform_id Number

    The platform ID to target the compilation

  • product_id String

    The product to target for compilation

  • build_target_version String

    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"
}

List firmware build targets

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.

  • featured REQUIRED Boolean

    When true, show most relevant (featured) build targets only.

$ curl https://api.particle.io/v1/build_targets
  • targets Array

    Array of build target objects

  • platforms Object

    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.

Lock product device

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
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug REQUIRED String

    Product ID or slug. Product endpoint only

  • desired_firmware_version REQUIRED Number

    The firmware version the device should be locked to

  • flash Boolean

    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"
  • id String

    Device ID

  • desired_firmware_version String

    The newly set firmware version to lock the device to

  • updated_at Date

    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"
}

Unlock product device

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
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug REQUIRED String

    Product ID or slug. Product endpoint only

  • desired_firmware_version REQUIRED Number

    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"
  • id String

    Device ID

  • desired_firmware_version String

    Should now be null signaling that the device is no longer locked to a specific version of firmware

  • updated_at Date

    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"
}

Mark product development device

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
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug REQUIRED String

    Product ID or slug

  • development REQUIRED Boolean

    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"
  • id String

    Device ID

  • development String

    Should now be true signaling that the device is now a development device

  • updated_at Date

    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"
}

Unmark product development device

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
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug REQUIRED String

    Product ID or slug

  • development REQUIRED Boolean

    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"
  • id String

    Device ID

  • development String

    Should now be false signaling that the device is not a development device

  • updated_at Date

    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"
}

Firmware API limits

While compiling source code using the cloud compiler, or flashing a device with source code, there are limits:

  • Maximum time to compile: 120 seconds
  • Maximum source code size: 50 MB

This affects the following endpoints:

POST /v1/binaries
PUT /v1/devices/:deviceId

Product firmware

Get product firmware

GET /v1/products/:productIdOrSlug/firmware/:version

Get a specific version of product firmware

  • firmware:get
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • version REQUIRED Number

    Version number of firmware to retrieve

$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware/1 \
       -H "Authorization: Bearer :access_token"
  • _id String

    The ID of the firmware

  • version Number

    The version number of the firmware

  • title String

    The title of the firmware

  • description String

    A description of the firmware

  • name String

    The firmware's file name

  • size Number

    The size of the firmware in bytes

  • product_default Boolean

    Whether the firmware is released as the product default

  • groups Object

    An array of group names representing the groups the firmware version has been released to

  • mandatory Boolean

    [Enterprise only] Product upgrades and downgrades apply this version of firmware before flashing the targeted version.

  • uploaded_on Date

    Timestamp of when the firmware was uploaded

  • product_id Number

    The ID of the product that owns the firmware

  • uploaded_by Object

    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",
        ...
    }
}

List all product firmwares

GET /v1/products/:productIdOrSlug/firmware

List all versions of product firmware

  • firmware:list
  • productIdOrSlug REQUIRED String

    Product ID or slug

$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware \
       -H "Authorization: Bearer :access_token"
  • - Object[]

    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
     },
    ...
]

Upload product firmware

POST /v1/products/:productIdOrSlug/firmware

Upload a new firmware version to a product

  • firmware:create
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • version REQUIRED Number

    The version number of the firmware binary you are uploading

  • title REQUIRED String

    Title of the firmware version. Handy for quickly identifying the firmware

  • file REQUIRED File

    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

  • productIdOrSlug REQUIRED String

    Product ID or slug

  • description String

    Optionally provide a description for the new firmware version

  • mandatory REQUIRED Boolean

    [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
  • - Object

    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",
        ...
    }
}

Edit product firmware

PUT /v1/products/:productIdOrSlug/firmware/:version

Edit a specific product firmware version

  • firmware:update
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • version REQUIRED String

    Version number of the firmware to edit

  • title String

    Provide a new title for the firmware

  • description String

    Provide a new description for the firmware

  • mandatory REQUIRED Boolean

    [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"
  • - Object

    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",
        ...
    }
}

Download firmware binary

GET /v1/products/:productIdOrSlug/firmware/:version/binary

Retrieve and download the original binary of a version of product firmware.

  • firmware.binary:get
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • version REQUIRED Number

    Version number of firmware to retrieve

$ curl https://api.particle.io/v1/products/:productIdOrSlug/firmware/1/binary \
       -H "Authorization: Bearer :access_token"
  • - File

    The binary file of the requested product firmware version

Release product firmware

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
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • version REQUIRED Number

    firmware version number to release to the fleet

  • product_default Boolean

    Pass true to set the firmware version as the product default release

  • groups String

    An array of device groups to release the firmware to.

  • intelligent REQUIRED Boolean

    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"
  • - Object

    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 unreleased firmware binary

DELETE /v1/products/:productIdOrSlug/firmware/:version

Delete a version of product firmware that has never been released.

  • firmware:remove
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • version REQUIRED Number

    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

Libraries

The libraries endpoints are a little different as they follow the JSON API specification.

List libraries

GET /v1/libraries

List firmware libraries. This includes private libraries visibile only to the user.

  • filter String

    Search for libraries with this partial name

  • page "1"

    Page number

  • limit "10"

    Items per page (max 100)

  • sort "popularity"

    Sort order for results. Prefix with - for descending order.

    • name
    • installs
    • popularity
    • published
    • updated
    • created
    • official
    • verified
  • scope "all"

    Which subset of libraries to list.

    • all to retrieve public libraries and any private libraries belonging to the user
    • official to retrieve official public libraries
    • public to retrieve public libraries
    • mine to retrieve only public libraries belonging to the current user
    • private to retrieve only private libraries (belonging to the current user).
  • excludeScopes String

    Which subsets of libraries to avoid listing, separated by comma. Same values as scope.

  • architectures String

    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"
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 library details

GET /v1/libraries/:libraryName

Get details for a firmware library.

  • libraryName REQUIRED String

    Name of library to retrieve (case insensitive)

  • version "latest"

    Version to retrieve. Defaults to the latest version.

  • scope "all"

    Which subset of versions to get.

    • all
    • public
    • private
$ curl https://api.particle.io/v1/libraries/internetbutton \
       -H "Authorization: Bearer :access_token"
  • data object

    The library version in JSON API format

  • data.id string

    The name of the library

  • data.links.download string

    The URL to download the files for this library

  • data.attributes string

    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 library versions

GET /v1/libraries/:libraryName/versions

Get details for all versions of a firmware library.

  • libraryName REQUIRED String

    Name of library to retrieve (case insensitive)

  • scope "all"

    Which subset of versions to get.

    • all
    • public
    • private
$ curl https://api.particle.io/v1/libraries/internetbutton\versions \
       -H "Authorization: Bearer :access_token"
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
      }
    }
  ]
}

Upload library version

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.

  • libraryName REQUIRED String

    Name of library to retrieve (case insensitive)

  • archive REQUIRED File

    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"
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"
    }
  ]
}

Make a library version public

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.

  • libraryName REQUIRED String

    Name of library to retrieve (case insensitive)

  • visibility REQUIRED String

    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"
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"
    }
  }
}

Products

List products

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"
  • products Object[]

    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
    }
  }]
}

Retrieve a product

GET /v1/products/:productIdOrSlug

Retrieve details for a product.

  • products:get
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • product Object
  • product.id String

    Product Unique ID

  • product.product_id Number

    Product Firmware ID

  • product.name String

    Product Name

  • product.slug String

    URL compatible version of name

  • product.description String
  • product.platform_id Number

    Product Platform ID

  • product.organization String

    Organization Unique ID

  • product.requires_activation_codes Boolean
  • product.device_protection String

    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"
  }
}

List team members

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
  • productIdOrSlug REQUIRED String

    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"
  • team Object[]

    An array of team members

  • team._id String

    ID of the team member

  • team.username String

    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
    },
     ...
  ]
}

Invite team member

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • username REQUIRED String

    Username of the invitee. Must be a valid email associated with an Particle user

  • role REQUIRED String

    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"
  • - Object

    The invited user

POST /v1/products/:productIdOrSlug/team
HTTP/1.1 200 OK
{
     "ok": true,
     "invited": {
        "username": "test@example.com"
  }
}

Create an API user

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • friendly_name REQUIRED String

    A friendly name used to recognise the user

  • scopes REQUIRED String[]

    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"]
           }'
  • - Object

    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"
     ]
  }
}

Update team member

POST /v1/products/:productIdOrSlug/team/:username

Update a current team member.

  • teams.users:update
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • username REQUIRED String

    Username of the team member to be updated

Remove team member

DELETE /v1/products/:productIdOrSlug/team/:username

Remove a current team member.

  • teams.users:remove
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • username REQUIRED String

    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
 }

Regenerate programmatic user's token

PUT /v1/products/:productIdOrSlug/team/:username/token

Regenerate programmatic users token

  • teams.users:update
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • username REQUIRED String

    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

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 device group

GET /v1/products/:productIdOrSlug/groups/:groupName

Retrieve full info on a specific product group, including its device count.

  • groups:get
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • groupName REQUIRED String

    The group name to fetch

$ curl https://api.particle.io/v1/products/:productIdOrSlug/groups/group_a \
       -H "Authorization: Bearer :access_token"
  • group Object

    The group object

  • group.name String

    The name of the group

  • group.description String

    A description of the group

  • group.color String

    A hex value representing of the color displayed next to the group tag on the Console

  • group.fw_version String

    The version number of the product firmware that has been released to this group

  • group.device_count Number

    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
  }
}

List device groups

GET /v1/products/:productIdOrSlug/groups

List the group objects that exist in the product. Optionally, filter by group name (partial match).

  • groups:list
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • name String

    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"
  • groups Object[]

    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"
    }
  ]
}

Create device group

POST /v1/products/:productIdOrSlug/groups

Create a new device group withinin a product

  • groups:create
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • name REQUIRED String

    The name of the group. Must only contain lowercase letters, numbers, dashes, and underscores.

  • color String

    A hex value representing of the color displayed next to the group tag on the Console

  • description String

    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"
  • group Object

    The group object

POST /v1/products/:productIdOrSlug/groups
HTTP/1.1 201 Created
{
  "group": {
    "name": "group_a",
    "description": "the A group",
    "color": "#34495e"
  }
}

Edit device group

PUT /v1/products/:productIdOrSlug/groups/:groupName

Edit attributes of a specific device group. You must pass one of name, color, or description.

  • groups:update
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • groupName REQUIRED String

    The group name to edit

  • name String

    Provide a new group name

  • color String

    Provide a new group color

  • description String

    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"
  • group Object

    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 device group

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
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • groupName REQUIRED String

    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

Assign groups to a device

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
  • deviceId REQUIRED String

    Device ID

  • productIdOrSlug REQUIRED String

    Product ID or slug

  • groups REQUIRED Object[]

    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"
  • id String

    Device ID

  • groups Object[]

    Array of updated device group names

  • updated_at Date

    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"
}

Batch assign groups to devices

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
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • action REQUIRED String

    Set to groups

  • devices REQUIRED Object[]

    An array of device IDs to update group memberships

  • metadata REQUIRED Object

    metadata object to inform which groups should be added/removed

  • metadata.add Object[]

    Array of group names to add to devices

  • metadata.remove Object[]

    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
}

Impact of taking action

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
  • productIdOrSlug REQUIRED String

    Product ID or slug

  • action REQUIRED String

    The action you are about to take. Currently only accepts edit_groups_for_firmware

  • firmware_version REQUIRED String

    Firmware version you wish to release

  • groups String

    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.

  • product_default Boolean

    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"
  • firmware_update Object

    object containing impact details

  • firmware_update.total Number

    number of devices which will get OTA update resulting from the planned groups action

  • firmware_update.by_version Object[]

    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
         },
         {
               ...
         }
       ]
     }
   }
}

Asset tracking

Location

Query fleet-wide locations for devices within a product

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • device_id String

    Device ID prefix to include in the query

  • device_name String

    Device name prefix to include in the query

  • groups String[]

    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
      ]
    },
  }]
}

Query location for devices within a product

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • date_range String

    Start and end date in ISO8601 format, separated by comma, to query. Omitting date_range will return last known location.

  • rect_bl String

    Bottom left of the rectangular bounding box to query. Latitude and longitude separated by comma.

  • rect_tr String

    Top right of the rectangular bounding box to query. Latitude and longitude separated by comma.

  • device_id String

    Device ID prefix to include in the query

  • device_name String

    Device name prefix to include in the query

  • groups String[]

    Array of group names to include in the query

  • page Number

    Page of results to display. Defaults to 1

  • per_page Number

    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,
  }
}

Query location for one device within a product

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceId REQUIRED String

    Device ID

  • date_range String

    Start and end date in ISO8601 format, separated by comma, to query. Omitting date_range will return last known location.

  • rect_bl String

    Bottom left of the rectangular bounding box to query. Latitude and longitude separated by comma.

  • rect_tr String

    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": {}
}

Configuration

Get product configuration

GET /v1/products/:productIdOrSlug/config

Get the configuration values that are the default for the product

  • productIdOrSlug REQUIRED String

    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 device configuration

GET /v1/products/:productIdOrSlug/config/:deviceId

Get the configuration values that are specific to this device

  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceId REQUIRED String

    The device ID to query.

$ curl https://api.particle.io/v1/products/1234/config/abc123 -H "Authorization: Bearer :access_token"
  • configuration Object
  • configuration.current Object

    The device's current confirmed configuration

  • configuration.pending Object

    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 product schema

GET /v1/products/:productIdOrSlug/config

Get the possible values that can be configured for this product, in JSON Schema format

  • Accept REQUIRED String

    Must be set to "application/schema+json" for this endpoint

  • configuration:get
  • productIdOrSlug REQUIRED String

    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 device schema

GET /v1/products/:productIdOrSlug/config/:deviceId

Get the possible values that can be configured for one device in this product, in JSON Schema format

  • Accept REQUIRED String

    Must be set to "application/schema+json" for this endpoint

  • configuration:get
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceId REQUIRED String

    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 product configuration schema

DELETE /v1/products/:productIdOrSlug/config

Delete configuration schema, use Tracker Edge defaults.

  • Content-Type REQUIRED String

    Must be set to "application/schema+json" for this endpoint.

  • configuration:update
  • productIdOrSlug REQUIRED String

    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

Set product configuration

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceIds String[]

    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
{}

Set product configuration schema

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.

  • Content-Type REQUIRED String

    Must be set to "application/schema+json" for this endpoint.

  • configuration:update
  • productIdOrSlug REQUIRED String

    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 device configuration schema

DELETE /v1/products/:productIdOrSlug/config/:deviceId

Delete device's configuration schema, use product's.

  • Content-Type REQUIRED String

    Must be set to "application/schema+json" for this endpoint.

  • configuration:update
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceId REQUIRED String

    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

Set device configuration

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

  • 200 when the device is online and accepted the configuration changes.
  • 202 when the device is offline. We'll complete the request when it comes online again
  • 400 When the device is online, but has rejected some of the configuration keys. A list of accepted and rejected keys with device error codes is provided

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceId REQUIRED String

    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'
}

Set device configuration schema

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.

  • Content-Type REQUIRED String

    Must be set to "application/schema+json" for this endpoint.

  • configuration:update
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • deviceId REQUIRED String

    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"
      }
   ]
}

Logic

Execute logic function

POST /v1/users/logic/execute

Executes the provided logic function.

  • logic.functions:execute
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • source REQUIRED Object

    Logic function code to debug

  • source.type REQUIRED String

    Type of code (always JavaScript)

  • source.code REQUIRED String

    Code to execute

  • event REQUIRED Object

    Event to trigger the logic function

  • event.event_data REQUIRED String

    Event name

  • event.event_data REQUIRED String

    Event data

  • event.device_id REQUIRED String

    Device ID that triggered the event

  • event.product_id REQUIRED String

    Product ID that triggered the event

  • api_username REQUIRED String

    Optional API user to access Particle API

$ curl "https://api.particle.io/v1/users/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/users/logic/execute
HTTP/1.1 200 OK
{
  "result": {
    "status": "Success",
    "logs": []
  }
}

List logic functions

GET /v1/users/logic/functions

Lists all logic functions belonging to the specified Sandbox or organization.

  • logic.functions:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • today_stats Boolean

    Include today's stats

$ curl "https://api.particle.io/v1/users/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/users/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 logic function

GET /v1/users/logic/functions/:logicFunctionId

Returns the specified logic function.

  • logic.functions:get
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

$ curl "https://api.particle.io/v1/users/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/users/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"
      }
    ]
  }
}

Create a new logic function

POST /v1/users/logic/functions

Creates a logic function.

  • logic.functions:create
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logic_function REQUIRED Object

    Logic function

$ curl "https://api.particle.io/v1/users/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/users/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"
      }
    ]
  }
}

Update logic function

PUT /v1/users/logic/functions/:logicFunctionId

Updates the logic function.

  • logic.functions:update
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

  • logic_function REQUIRED Object

    Logic function

$ curl -X PUT "https://api.particle.io/v1/users/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/users/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 logic function

DELETE /v1/users/logic/functions/:logicFunctionId

Deletes the specified logic function.

  • logic.functions:remove
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

$ curl -X DELETE "https://api.particle.io/v1/users/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/users/logic/functions/:logicFunctionId
HTTP/1.1 204 No content

List logic functions runs

GET /v1/users/logic/functions/:logicFunctionId/runs

Lists all runs for the specified logic function.

  • logic.runs:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

$ curl "https://api.particle.io/v1/users/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/users/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 logic function run

GET /v1/users/logic/functions/:logicFunctionId/runs/:logicRunId

Returns the specified logic function run.

  • logic.runs:get
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

  • logicRunId REQUIRED String

    Logic run ID

$ curl "https://api.particle.io/v1/users/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/users/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 logic function run logs

GET /v1/users/logic/functions/:logicFunctionId/runs/:logicRunId/logs

Returns the specified logic function run logs.

  • logic.logs:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

  • logicRunId REQUIRED String

    Logic run ID

$ curl "https://api.particle.io/v1/users/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/users/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 logic function stats

GET /v1/users/logic/functions/:logicFunctionId/stats

Returns the specified logic function stats.

  • logic.stats:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • logicFunctionId REQUIRED String

    Logic function ID

$ curl "https://api.particle.io/v1/users/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/users/logic/functions/:logicFunctionId/stats
HTTP/1.1 200 OK
{
   "logic_function_stats": [
     {
       "date": "20231106",
       "success": 175,
       "failure": 168,
       "timeout": 0
     }
   ]
}

Ledger

List ledger definitions

GET /v1/users/ledgers

Lists all ledger definitions belonging to the Sandbox or organization.

  • ledger.definitions:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • page Number

    Page number

  • perPage Number

    Number of definitions per page

  • archived Boolean

    Filter for archived definitions

$ curl "https://api.particle.io/v1/users/ledgers" \
       -H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/ledgers" \
       -H "Authorization: Bearer :access_token"
GET /v1/users/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 ledger definition

GET /v1/users/ledgers/:ledgerName

Returns the specified ledger definition.

  • ledger.definitions:get
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

$ curl "https://api.particle.io/v1/users/ledgers/:ledgerName" \
       -H "Authorization: Bearer :access_token"
$ curl "https://api.particle.io/v1/orgs/:orgIdOrSlug/ledgers/:ledgerName" \
       -H "Authorization: Bearer :access_token"
GET /v1/users/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
  }
}

Create a new ledger definition

POST /v1/users/ledgers

Creates a ledger definition.

  • ledger.definitions:create
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • definition REQUIRED Object

    Ledger definition

$ curl "https://api.particle.io/v1/users/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/users/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
  }
}

Update ledger definition

PUT /v1/users/ledgers/:ledgerName

Updates the ledger definition.

  • ledger.definitions:update
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • definition REQUIRED Object

    Ledger definition

$ curl -X PUT "https://api.particle.io/v1/users/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/users/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
  }
}

Archive a ledger definition

DELETE /v1/users/ledgers/:ledgerName

Archives a ledger definition.

  • ledger.definitions:archive
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

$ curl -X DELETE "https://api.particle.io/v1/users/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/users/ledgers/:ledgerName
HTTP/1.1 204 No content

List ledger instances

GET /v1/users/ledgers/:ledgerName/instances

Lists all ledger instances.

  • ledger.instances:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • page Number

    Page number

  • perPage Number

    Number of instances per page

$ curl "https://api.particle.io/v1/users/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/users/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 ledger instance

GET /v1/users/ledgers/:ledgerName/instances/:scopeValue

Returns the specified ledger instance.

  • ledger.instances:get
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • scopeValue REQUIRED String

    Scope value

$ curl "https://api.particle.io/v1/users/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/users/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 ledger instance version

GET /v1/users/ledgers/:ledgerName/instances/:scopeValue/versions/:version

Returns the specified version of a ledger instance.

  • ledger.instances.versions:get
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • scopeValue REQUIRED String

    Scope value

  • version REQUIRED String

    Version ID

$ curl "https://api.particle.io/v1/users/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/users/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",
  }
}

Set the ledger instance data

PUT /v1/users/ledgers/:ledgerName/instances/:scopeValue

Sets the data of the specified ledger instance.

  • ledger.instances:set
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • scopeValue REQUIRED String

    Scope value

  • data REQUIRED Object

    Ledger instance data

$ curl -X PUT "https://api.particle.io/v1/users/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/users/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 ledger instance

DELETE /v1/users/ledgers/:ledgerName/instances/:scopeValue

Deletes the specified ledger instance.

  • ledger.instances:remove
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • scopeValue REQUIRED String

    Scope value

$ curl -X DELETE "https://api.particle.io/v1/users/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/users/ledgers/:ledgerName/instances/:scopeValue
HTTP/1.1 204 No content

List ledger instance versions

GET /v1/users/ledgers/:ledgerName/instances/:scopeValue/versions

Lists all ledger instance versions.

  • ledger.instances.versions:list
  • orgIdOrSlug String

    Organization ID or Slug. Organization endpoint only.

  • ledgerName REQUIRED String

    Ledger name

  • scopeValue REQUIRED String

    Scope value

  • replaced_before String

    List only versions replaced before this date

  • replaced_after String

    List only versions replaced after this date

$ curl "https://api.particle.io/v1/users/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/users/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
   }
}

Fleet Health

Get online devices metrics

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • start_date Date

    DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.

  • end_date Date

    DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.

  • bucket_size Number

    Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.

  • product_fw Number

    Filter for this product firmware version.

  • device_os_version String

    Filter for this Device OS version.

  • device_group String

    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"
  • online Object[]

    An array of online devices metrics

  • online.time Date

    The start of the time bucket. Date in ISO8601 format.

  • online.count Number

    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 event traffic health metrics

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • start_date Date

    DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.

  • end_date Date

    DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.

  • bucket_size Number

    Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.

  • product_fw Number

    Filter for this product firmware version.

  • device_os_version String

    Filter for this Device OS version.

  • device_group String

    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"
  • events Object[]

    An array of events metrics

  • events.time Date

    The start of the time bucket. Date in ISO8601 format.

  • events.received Number

    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 integration traffic health metrics

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • start_date Date

    DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.

  • end_date Date

    DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.

  • bucket_size Number

    Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.

  • product_fw Number

    Filter for this product firmware version.

  • device_os_version String

    Filter for this Device OS version.

  • device_group String

    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"
  • integrations Object[]

    An array of integration metrics

  • integrations.time Date

    The start of the time bucket. Date in ISO8601 format.

  • integrations.success Number

    The number of successful integrations in this bucket.

  • integrations.failure Number

    The number of failed integrations in this bucket.

  • integrations.sleep Number

    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 cloud function call health metrics

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • start_date Date

    DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.

  • end_date Date

    DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.

  • bucket_size Number

    Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.

  • product_fw Number

    Filter for this product firmware version.

  • device_os_version String

    Filter for this Device OS version.

  • device_group String

    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"
  • functions Object[]

    An array of functions metrics

  • functions.time Date

    The start of the time bucket. Date in ISO8601 format.

  • functions.success Number

    The number of successful function calls in this bucket.

  • functions.failure Number

    The number of failed function calls in this bucket.

  • functions.offline Number

    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 cloud variable request health metrics

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
  • productIdOrSlug REQUIRED String

    Product ID or slug.

  • start_date Date

    DateTime to start on (inclusive), defaults to the current time. Date in ISO8601 format.

  • end_date Date

    DateTime to end on (inclusive), defaults to the current time. Date in ISO8601 format.

  • bucket_size Number

    Number of seconds for each bucket, defaults to 900 (15 minutes). Must be greater than 15.

  • product_fw Number

    Filter for this product firmware version.

  • device_os_version String

    Filter for this Device OS version.

  • device_group String

    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"
  • variables Object[]

    An array of variables metrics

  • variables.time Date

    The start of the time bucket. Date in ISO8601 format.

  • variables.success Number

    The number of successful variable requests in this bucket.

  • variables.failure Number

    The number of failed variable requests in this bucket.

  • variables.offline Number

    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
    },
    ...
  ]
}

Customers

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.

Create a customer - Access token

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).

  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • email REQUIRED String

    Email Address or a unique identifier

  • password REQUIRED String

    Password

POST /v1/products/photon/customers
HTTP/1.1 201 OK
{
    "token_type": "bearer",
    "access_token": "92b6d13edaab936b016d54266a46134160f087e8",
    "refresh_token": "14b4d13edaab634b019d54265a46132160f017e8",
    "expires_in": 7776000
}

Create a customer - Client credentials

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.

  • Authorization REQUIRED String

    HTTP Basic Auth where username is the OAuth client ID and password is the OAuth client secret.

  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • client_id REQUIRED String

    OAuth client ID. Required if no Authorization header is present.

  • client_secret REQUIRED String

    OAuth client secret. Required if no Authorization header is present.

  • email REQUIRED String

    Email Address

  • password String

    Password

  • no_password Boolean

    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
}

Create a customer - Implicit

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.

  • Authorization REQUIRED String

    HTTP Basic Auth where username is the OAuth client ID and password is blank.

  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • client_id REQUIRED String

    OAuth client ID. Required if no Authorization header is present.

  • email REQUIRED String

    Email Address

  • password REQUIRED String

    Password

  • response_type String

    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

List customers for a product

GET /v1/products/:productIdOrSlug/customers

List Customers for a product.

  • customers:list
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • customers Object[]

    List of Customers

  • devices Object[]

    List of Devices that belong to those customers

  • customers.id String

    Customer ID

  • customers.username String

    Username

  • customers.devices String[]

    List of Device IDs

  • devices.id String

    Device ID

  • devices.product_id Number

    Product ID

  • devices.last_ip_address String

    Last known IP Address

  • devices.firmware_version Number

    Firmware Version

  • devices.online Boolean

    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
  }
}

Generate a customer scoped access token

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.

  • Content-Type REQUIRED String

    Must be set to application/x-www-form-urlencoded

  • Authorization REQUIRED String

    HTTP Basic Auth where username is the OAuth client ID and password is the OAuth client secret.

  • client_id String

    OAuth client ID. Required if no Authorization header is present.

  • client_secret String

    OAuth client secret. Required if no Authorization header is present.

  • grant_type REQUIRED String

    OAuth grant type. Must be client_credentials.

  • expires_in Number

    How many seconds the token will be valid for. 0 means forever. Short lived tokens are better for security.

  • expires_at Date

    When should the token expire? This should be an ISO8601 formatted date string.

  • scope 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"
  • access_token String

    The magical token you will use for all the other requests

  • token_type String

    Always set to "Bearer"

  • expires_in String

    The number of seconds this token is valid for. 0 means forever.

  • refresh_token String

    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"
}

Update customer password

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • customerEmail REQUIRED String

    Email of the customer account that you'd like to update

  • password REQUIRED String

    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 a customer

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
  • productIdOrSlug REQUIRED String

    Product ID or Slug

  • customerEmail REQUIRED String

    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}

Reset password (simple auth)

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:

  1. Customer loses access, clicks "forgot password" on your mobile or front-end app.
  2. App hits an endpoint on your back-end. The back-end app should know your Particle access token, the one you used to create that product, and, optionally, list of valid customer emails.
  3. This triggers an email to the customer sent from your back-end. This email can have your brand, logo, colors, etc. The email contains link to reset his or her password. Behind the scenes, a short-lived reset password token is created and stored in your back-end database.
  4. The email links to your hosted, brand-themed webpage that shows the a "set new password" field and verifies the reset password token. The customer types in new password, and the front-end hits an endpoint on your back-end with the new password.
  5. The back-end hits the update customer password API.
  6. Customer password is reset.
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.

Service agreements and usage

Get user service agreements

GET /v1/user/service_agreements

Get the service agreements related to a user

  • id String

    Service agreement Unique ID

  • type String

    Object type

  • attributes Object

    Service agreement attributes

  • attributes.owner_id String

    Service agreement owner

  • attributes.agreement_type String

    Service agreement type

  • attributes.duration String

    Billing period duration

  • attributes.state String

    Indicates if the service agreement is active

  • attributes.starts_on String

    Date when the service agreement started

  • attributes.ends_on String

    service Agreements ends date

  • attributes.current_billing_period_start String

    Current billing period start date

  • attributes.current_usage_summary Object

    Usage summary for the period

  • attributes.current_usage_summary.device_limit_reached Boolean

    Indicates if the device limit was reached

  • attributes.current_usage_summary.connectivity Object

    Info about the connectivity devices grouped by device type

  • attributes.pricing_terms Object

    All related with the selected pricing model

  • attributes.pricing_terms.rates Object

    Rates limits and consumption period

  • attributes.pricing_terms.device Object

    Device limits and consumption period

  • attributes.pricing_terms.messaging Object

    Message limits and consumption period

  • attributes.pricing_terms.device_data Object

    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 organization service agreements

GET /v1/orgs/:orgIdOrSlug/service_agreements

Get the service agreements related to an organization

  • service_agreements:list
  • orgIdOrSlug REQUIRED String

    Org ID or Slug

  • id String

    Service agreement Unique ID

  • type String

    Object type

  • attributes Object

    Service agreement attributes

  • attributes.owner_id String

    Service agreement owner

  • attributes.agreement_type String

    Service agreement type

  • attributes.duration String

    Billing period duration

  • attributes.state String

    Indicates if the service agreement is active

  • attributes.starts_on String

    Date when the service agreement started

  • attributes.ends_on String

    service Agreements ends date

  • attributes.current_billing_period_start String

    Current billing period start date

  • attributes.current_usage_summary Object

    Usage summary for the period

  • attributes.current_usage_summary.device_limit_reached Boolean

    Indicates if the device limit was reached

  • attributes.current_usage_summary.connectivity Object

    Info about the connectivity devices grouped by device type

  • attributes.pricing_terms Object

    All related with the selected pricing model

  • attributes.pricing_terms.rates Object

    Rates limits and consumption period

  • attributes.pricing_terms.device Object

    Device limits and consumption period

  • attributes.pricing_terms.messaging Object

    Message limits and consumption period

  • attributes.pricing_terms.device_data Object

    Device data limits and consumption period

  • attributes.pricing_terms.support Object

    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 a user usage report

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.

  • usageReportId REQUIRED Integer

    The usage report ID

$ curl "https://api.particle.io/v1/user/usage_reports/:userReportId" \
       -H "Authorization: Bearer :access_token"
  • id String

    Usage Report Unique ID

  • type String

    Object type

  • attributes Object

    Usage Report attributes

  • attributes.state String

    Usage Report current state

  • attributes.service_agreement_id String

    Service Agreement Unique ID

  • attributes.date_period_start String

    The start of the date period to query

  • attributes.date_period_end String

    The end of the date period to query

  • attributes.created_at String

    UTC timestamp of when the Usage Report request was created

  • attributes.expires_at String

    UTC timestamp of when the Usage Report file expires

  • attributes.report_type String

    Usage Report type

  • attributes.report_params Object

    Usage Report parameters

  • attributes.report_params.devices Array

    List of Device Unique IDs

  • attributes.report_params.products Array

    List of Product Unique IDs

  • attributes.report_params.recipient_list Array

    List of emails to send the report via email

  • attributes.download_url String

    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 an org usage report

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
  • usageReportId REQUIRED Integer

    The usage report ID

  • orgSlugOrId REQUIRED String

    Organization Slug or ID

$ curl "https://api.particle.io/v1/orgs/:orgSlugOrId/usage_reports/:usageReportId" \
       -H "Authorization: Bearer :access_token"
  • id String

    Usage Report Unique ID

  • type String

    Object type

  • attributes Object

    Usage Report attributes

  • attributes.state String

    Usage Report current state

  • attributes.service_agreement_id String

    Service Agreement Unique ID

  • attributes.date_period_start String

    The start of the date period to query

  • attributes.date_period_end String

    The end of the date period to query

  • attributes.created_at String

    UTC timestamp of when the Usage Report request was created

  • attributes.expires_at String

    UTC timestamp of when the Usage Report file expires

  • attributes.report_type String

    Usage Report type

  • attributes.report_params Object

    Usage Report parameters

  • attributes.report_params.devices Array

    List of Device Unique IDs

  • attributes.report_params.products Array

    List of Product Unique IDs

  • attributes.report_params.recipient_list Array

    List of emails to send the report via email

  • attributes.download_url String

    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
  }
}

Create a user usage report

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
  • serviceAgreementId REQUIRED Integer

    Service Agreement ID

  • report_type REQUIRED String

    One of the supported report types, "devices" or "products"

  • date_period_start REQUIRED String

    The start of the date period to query

  • date_period_end REQUIRED String

    The end of the date period to query

  • devices String[]

    An optional array of Device IDs

  • products String[]

    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"]
       }'
  • id String

    Usage Report Unique ID

  • type String

    Object type

  • attributes Object

    Usage Report attributes

  • attributes.state String

    Usage Report current state

  • attributes.service_agreement_id String

    Service Agreement Unique ID

  • attributes.date_period_start String

    The start of the date period to query

  • attributes.date_period_end String

    The end of the date period to query

  • attributes.created_at String

    UTC timestamp of when the Usage Report request was created

  • attributes.expires_at String

    UTC timestamp of when the Usage Report file expires

  • attributes.report_type String

    Usage Report type

  • attributes.report_params Object

    Usage Report parameters

  • attributes.report_params.devices Array

    List of Device Unique IDs

  • attributes.report_params.products Array

    List of Product Unique IDs

  • attributes.report_params.recipient_list Array

    List of emails to send the report via email

  • attributes.download_url String

    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
  }
}

Create an org usage report

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.

  • orgSlugOrId REQUIRED String

    Organization Slug or ID

  • serviceAgreementId REQUIRED Integer

    Service Agreement ID

  • report_type REQUIRED String

    One of the supported report types, "devices" or "products"

  • date_period_start REQUIRED String

    The start of the date period to query

  • date_period_end REQUIRED String

    The end of the date period to query

  • devices String[]

    An optional array of Device IDs

  • products String[]

    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"]
       }'
  • id String

    Usage Report Unique ID

  • type String

    Object type

  • attributes Object

    Usage Report attributes

  • attributes.state String

    Usage Report current state

  • attributes.service_agreement_id String

    Service Agreement Unique ID

  • attributes.date_period_start String

    The start of the date period to query

  • attributes.date_period_end String

    The end of the date period to query

  • attributes.created_at String

    UTC timestamp of when the Usage Report request was created

  • attributes.expires_at String

    UTC timestamp of when the Usage Report file expires

  • attributes.report_type String

    Usage Report type

  • attributes.report_params Object

    Usage Report parameters

  • attributes.report_params.devices Array

    List of Device Unique IDs

  • attributes.report_params.products Array

    List of Product Unique IDs

  • attributes.report_params.recipient_list Array

    List of emails to send the report via email

  • attributes.download_url String

    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 notifications for current usage period

GET /v1/user/service_agreements/:serviceAgreementId/notifications

Get user notifications related to a specific service agreement

  • Usage reached a certain threshold (70%, 90%, 100%)
  • Service was paused
  • Service was unpaused
  • service_agreements.notifications:list
  • serviceAgreementId REQUIRED String

    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"
  • id String

    Notification Unique ID

  • type String

    Object type

  • attributes. Object

    Notification attributes

  • attributes.state String

    indicates the state of the notification

  • attributes.event_name String

    Notification event name

  • attributes.time_period String

    Notification time period

  • attributes.created_at String

    Notification created datetime

  • attributes.updated_at String

    Notification updated datetime

  • attributes.resource_id String

    Service agreement Id

  • attributes.resource_type String

    Notification resource type

  • attributes.details Object

    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"
                }
            }
        }
    ]
    }