Appearance
Devices & Properties
The flake module is the device tree: every device of the tenant, the services it exposes, and the current value of every property — served from the backend's cache of the last transmissions. Reads never wake a device; writes are queued and confirmed by the device.
{deviceId} accepts the device id or the IMEI throughout. Property ids are canonical hex strings (0x0800).
Reading devices, services and properties
One request returns the whole fleet with all current values:
js
const response = await client.fetch(
"GET",
"https://<<URL>>/api/v1/devices?depth=2&expand=propertyType,modifier",
{ accessToken },
);
const devices = await response.json();json
[
{
"crn": "crn#tenant:Ba9mN3pQ.device:A1B2C3D4",
"imei": "350000000000001",
"services": [
{
"serviceId": "00000000-0000-2001-8003-006d0099ab53",
"properties": [
{
"id": "0x0800",
"value": 215,
"measuredAt": 1756800000000,
"pending": null,
"propertyType": "UINT16",
"modifier": { "isReadOnly": true, "isActionable": false, "isVolatile": false, "isError": false, "isMeta": false, "isNull": false }
}
]
}
]
}
]depthfolds the hierarchy into one response:0devices only,1plus their services,2plus every current property.depth=2is usually all a dashboard needs at startup.expandadds optional per-property fields:propertyType,modifier,transmittedAt,streamData.pendingis non-null while a write to that property is still in flight (below).
For a single device or service there are direct routes:
text
GET /api/v1/devices/{deviceId}/services?depth=1
GET /api/v1/devices/{deviceId}/services/{serviceId}/properties
GET /api/v1/devices/{deviceId}/services/{serviceId}/properties/{propertyId}Human-readable names, units and enums for the raw values come from schemas; display names and locations from metadata.
Writing property values
Writes go through REST and are asynchronous by default — the backend queues the value for the device:
text
PUT /api/v1/devices/{deviceId}/services/{serviceId}/properties/0x0801js
await client.fetch(
"PUT",
"https://<<URL>>/api/v1/devices/A1B2C3D4/services/00000000-0000-2001-8003-006d0099ab53/properties/0x0801",
{
accessToken,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ value: 3 }),
},
);How to reason about a write:
- The property's
pendingfield is set immediately and stays non-null until the device confirms. Render pending state in your UI instead of optimistically showing the new value. - The confirmation is the next
OBJECT_UPDATEDevent for that service carrying the property — the same path every other value change takes. There is no separate "write succeeded" event. ?immediate=truemakes the write fail fast with an offline error instead of queueing when the device is not connected — for interactions where "later" is worse than "not at all".?retries=controls how often the backend retries delivery.- Several properties of one service can be written in one request:
PUT …/propertieswith[ { "id": "0x0801", "value": 3 }, … ].
Values follow the property's type; INT64/UINT64 travel as decimal strings, BIN/UUID as base64. Details: flake module reference.
Calling device methods
Where a schema defines methods for a service, you can invoke them by name — this is v5's replacement for addressing things by schema names in URLs:
text
POST /api/v1/devices/{deviceId}/services/{serviceId}/messages/{name}js
const response = await client.fetch(
"POST",
"https://<<URL>>/api/v1/devices/A1B2C3D4/services/00000000-0000-2001-8003-006d0099ab53/messages/reboot",
{
accessToken,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ params: [] }),
},
);Unlike property writes, a method call is synchronous: the device must be online, the call waits for the device's answer, and the response carries the properties the device returned (or an error outcome). Each parameter states its own id, type and value — the schema's method definition tells you which parameters a method takes.
Reference: POST /devices/…/messages/{name}.