Overview
Client-mode connector for the Particle Device Cloud API. Particle devices (Photon 2, Argon, Boron, B-SoM, M-SoM, Tracker) expose cloud variables that you read and cloud functions that you call, publish and subscribe to events, and keep shared JSON state in Ledger. Fleets are grouped in products; cellular devices come with Particle SIMs.- ParticleRestApi (
https://api.particle.io) lets the Coreflux broker read a machine value from a device, call a function to change a setpoint, broadcast an event to devices, check device vitals and SIM data usage, follow trackers on a map, and push setpoints to devices through a Cloud to Device ledger. - ParticleWebhookReceiver (
cloud-iot_particle_webhook.lot, opt-in, server mode) receives Particle webhooks so device events reach MQTT without polling.
Topics are
cloud-iot/particle/<object>/<verb> and every reply goes to <topic>/response. There are no DELETE events. product_id takes the product id or slug, org_id the organization id or slug.
See the base guide: REST API Connectors.
Factory live smoke is blocked until a Particle access token and a test device are supplied. The connectors were checked against Particle’s published API description and the live API without a token only.
Authentication
Every event sendsAuthorization: Bearer {access_token}.
- A user token is the quickest start:
particle token create(valid 90 days unless you pass--expires-in). It can do anything your account can. - For unattended plant use, create a product or organization API user with only the scopes its events need, for example
devices:list,devices.variable:get,devices.function:call,events:send,integrations:create,ledger.instances:getandledger.instances:set. An API user has one token at a time and must use the product (/v1/products/...) or organization (/v1/orgs/...) events.
PARTICLE_ACCESS_TOKEN, plus PARTICLE_DEVICE_ID / PARTICLE_PRODUCT_ID) and map it in with GET SECRET. Particle still accepts a token in the query string or a form body, but both are deprecated; this template uses the header only.
A missing token returns 400 {"error": "invalid_request", "error_description": "The access token was not found"}, a wrong or expired one 401 {"error": "invalid_token", ...}. Particle checks the token before it looks at the path, so a 400 / 401 does not tell you whether the path exists.
Basic Syntax
ParticleRestApi.lot in the REST API app.
MQTT examples
The connector sends only{value.json.body} as the request body. Keep access_token, device_id, product_id, org_id, variable_name, function_name, ledger_name, scope_value, iccid, integration_id and query at the top level of the MQTT payload. Device ids are the 24-character hex ids shown in the Particle console. Send "query": "" when you do not need query parameters.
Read a cloud variable: publish to cloud-iot/particle/device-variable/get:
{"name": "temperature", "result": 21.4, "coreInfo": {...}}; with "query": "format=raw" only 21.4. The device must be online: an offline device answers 404, a variable the firmware does not expose 400.
Call a cloud function: publish to cloud-iot/particle/device-function/call:
{"id": "...", "connected": true, "return_value": 1200}. The argument is a string of at most 63 characters.
Publish an event to devices: publish to cloud-iot/particle/event/publish:
Particle.subscribe("coreflux/line-porto-1/", handler). For a product fleet use cloud-iot/particle/product-event/publish with "product_id".
Push setpoints through Ledger: publish to cloud-iot/particle/ledger-instance/set:
set_mode=Replace (the default) overwrites the instance, Merge updates only the keys you send. Use the product-ledger-instance or org-ledger-instance events for product or organization ledgers.
Fleet checks: cloud-iot/particle/product-device/list with "query": "groups=porto-1&perPage=100", cloud-iot/particle/device-vitals/get for signal and battery, cloud-iot/particle/sim-data-usage/get with "iccid", and cloud-iot/particle/product-location/list with "query": "per_page=100" for tracker positions.
Receive Particle events (webhook receiver)
Polling variables costs a data operation per call. To get device events pushed to MQTT, deploy the companion filecloud-iot_particle_webhook.lot:
cloud-iot/particle/webhook/create:
Particle.publish("telemetry", ...) from your devices now arrives on cloud-iot/particle/webhook-telemetry/received. cloud-iot/particle/integration/test sends a test delivery.
- Deploying the receiver opens HTTP port
9001on the broker. - Particle delivers from its cloud to a public URL. Put a reverse proxy or tunnel with a public TLS certificate in front of port
9001and forward/particle/webhook/.... - Accept only Particle. The connector does not check secrets itself: let the proxy check the
Authorizationheader you set on the webhook (or Basicauth, or a Particle cloud secret inserted with{{{SECRET_NAME}}}). - Use the JSON request format. The default Web Form format arrives URL-encoded.
- Answer fast: Particle waits 20 seconds and throttles a webhook whose target fails or times out too often.
datais the string the device published (often JSON text): parse it in a LoT action. Retries can repeat a delivery, so deduplicate oncoreid+published_at.
Helper actions
Call a function from a plant setpoint topic, poll a variable every minute, and connector webhook telemetry per device, with the token and device id kept in broker secrets:cloud-iot/particle/# with a rule: its payloads carry the token, and the function, event and ledger events change how devices in the field behave.
Notes
- Rate limits: 10,000 API requests every 5 minutes per public IP address; a
429means slow down (retrying at once does not help). The serial-number lookup and the event streams have stricter limits. Polling many variables quickly hits the limit and costs data operations on cellular devices; prefer events plus the webhook receiver. - Errors come back on the response topic:
400(bad request, or the variable / function is not exposed),401(token invalid or expired),403(token not allowed for this device or product),404(device offline or unknown),408(the device did not answer in time),429,5xx. - Ledger: names are lowercase letters, digits and dashes, up to 32 characters. Device-synced ledgers hold up to 16 KB of JSON, cloud-only ledgers up to 1 MB. Device to Cloud and Cloud to Device ledgers need Device OS 6.1.0 or later. The API reference lists the set body as
{"data": ...}; the official JavaScript SDK sends{"instance": {"data": ...}}withset_mode. This template passes the body through unchanged, so either form can be sent. - Not packaged: Server-Sent Event streams (
GET /v1/devices/events/..., product and organization streams) because a REST_API connector cannot hold a stream open (use the webhook receiver instead), every DELETE (unclaim, remove from product, delete ledger instance, delete integration), firmware flashing and compiling, claiming and importing devices, SIM activation, customers, groups, Logic functions, environment variables, cloud secrets and OAuth clients. - Only the global host
https://api.particle.iois documented (TLS 1.2 or later).

