REST API
Base URL: https://api.staging.nodelets.com
Authentication
Section titled “Authentication”Every route except /health and /build needs an API key:
Authorization: Bearer nlt_...A missing, malformed or deleted key answers 401 with code UNAUTHENTICATED. Create keys on the dashboard’s Account page; see Create an API key with permissions.
Conventions
Section titled “Conventions”- Request and response bodies are JSON. Responses carry
Cache-Control: no-store. - A request body is at most 262,144 bytes. A larger body, or one that is not JSON, answers
INVALID_INPUT. - A call that reaches a device has a deadline of 10 seconds.
- A Nodelet the key does not reach answers
404 NOT_FOUND, the same as one that does not exist. A capability or operation the key is not given answers403 PERMISSION_DENIED. - Errors use the envelope described in Outcomes and errors.
Routes
Section titled “Routes”| Method and path | Permission | Answer |
|---|---|---|
GET /nodelets |
Any permission naming the Nodelet | The Nodelets the key reaches |
GET /nodelets/{id} |
Any permission naming the Nodelet | A summary of one Nodelet |
GET /nodelets/{id}/td |
Any permission naming the Nodelet | Its Thing Description |
GET /nodelets/{id}/properties/{name} |
Read value | The property’s current value |
PUT /nodelets/{id}/properties/{name} |
Write value | null |
POST /nodelets/{id}/actions/{name} |
Run action | The action’s output, or null |
GET /nodelets/{id}/record |
Read record | A page of the Nodelet’s record |
GET /nodelets/{id}/observations/recent |
Read history | A page of recent saved readings |
GET /nodelets/{id}/observations/archive |
Read history | A page of archived saved readings |
GET /observations/health |
Read history | Collection status for each Nodelet |
GET /bridges/{bridgeId}/stream |
See WebSocket | A WebSocket for live values and calls |
GET /observations/stream |
Read history | The account feed WebSocket |
GET /health |
None | {"status": "ok", "environment": "...", "buildId": "..."} |
Any other method on these paths answers an error. Nodelet IDs have the form nl_ followed by a UUID.
List Nodelets
Section titled “List Nodelets”GET /nodelets
{"items": [{"id": "nl_5c0e8a2f-7d41-4b9e-a3c6-2f8d1e4b7a90", "name": "Workshop heater", "bridgeId": "br_9a4f2c71-3e8b-4d06-b5a2-c1e7f0d38b64", "revision": 2}]}revision counts changes to the Nodelet’s definition and settings.
Nodelet summary
Section titled “Nodelet summary”GET /nodelets/{id}
| Field | Meaning |
|---|---|
id, name, bridgeId, revision |
As in the listing |
tdUrl |
The address of its Thing Description |
streamUrl |
The WebSocket address of its bridge, for live values |
bridgeConnected |
Whether its bridge is connected now |
The summary also carries connected, connectionId and routerInstanceId, which describe the bridge’s connection for diagnosis.
Thing Description
Section titled “Thing Description”GET /nodelets/{id}/td answers with content type application/td+json: a W3C Thing Description 1.1 holding only the capabilities and operations the key may use. See Definitions and Thing Descriptions.
Read a property
Section titled “Read a property”GET /nodelets/{id}/properties/{name} answers with the bare JSON value, read from the device for this request and checked against the definition:
21.5Write a property
Section titled “Write a property”PUT /nodelets/{id}/properties/{name} with the value as the body:
PUT /nodelets/nl_5c0e8a2f-7d41-4b9e-a3c6-2f8d1e4b7a90/properties/setpointAuthorization: Bearer nlt_...
22A value that does not match the property’s schema answers INVALID_INPUT with outcome not-executed, and nothing is sent. A successful write answers null. Nodelets does not read the value back.
Invoke an action
Section titled “Invoke an action”POST /nodelets/{id}/actions/{name} with the action’s input as the body. Send no body for an action with no input; a body for an action that declares no input answers INVALID_INPUT. The answer is the declared output, or null.
Record
Section titled “Record”GET /nodelets/{id}/record
| Parameter | Meaning |
|---|---|
before |
Optional. A seq from an earlier page’s nextBefore, to read older entries |
Answers {"entries": [...], "nextBefore": number | null, "startsAt": {"effects": {"seq", "at"} | null}}, newest first. A key sees writes and actions, with no refused attempts and no actor IDs. Each command entry has seq, correlationId, actor (kind and name), nameIsClaimed, operation, capability, value, admittedAt, sentAt, resultAt, outcome, reportedBy, code, definitionRevision and keyGeneration. A gap entry has seq, count, firstAt and lastAt.
| Field | Values |
|---|---|
outcome |
pending, done, not-executed, unknown |
reportedBy |
bridge, router, none: whose word the outcome is |
value.state |
kept, cut (shortened to 4,096 bytes), withheld (write-only), none (no value) |
value.callerSupplied is always true: the text came from a caller. startsAt.effects is set once the oldest entries have gone to stay within the record’s size limit. A removed Nodelet’s record answers NOT_FOUND to a key.
Saved readings
Section titled “Saved readings”GET /nodelets/{id}/observations/recent and GET /nodelets/{id}/observations/archive
| Parameter | Meaning |
|---|---|
property |
Optional. One property. Without it, the key needs Read history on all capabilities |
limit |
1 to 1,000. Default 100 |
cursor |
Optional. An earlier page’s nextCursor |
Any other parameter answers INVALID_INPUT. Both answer newest first:
| Field | Meaning |
|---|---|
observations |
Readings, each with property, value, receivedAt (milliseconds since the epoch, cloud time), sequence, sampleInterval and definitionRevision |
sampling |
{"type": "time", "everySeconds": n}, the sampling in force, or null |
nextCursor |
The cursor for the next page, or null |
uncertain |
Intervals on this page that history cannot vouch for, each with property, reason, count, firstAt and lastAt |
uncertainFrom |
Intervals before this time have gone, or null |
movedThrough |
{"sequence", "at"}: readings at or below this have moved to the archive, or null |
evictedThrough |
{"sequence", "at"}: readings at or below this have gone for good, or null |
An archive page can hold fewer readings than limit and still carry a nextCursor.
Collection health
Section titled “Collection health”GET /observations/health
{"nodelets": [{"id": "nl_5c0e8a2f-7d41-4b9e-a3c6-2f8d1e4b7a90", "bridgeId": "br_9a4f2c71-3e8b-4d06-b5a2-c1e7f0d38b64", "status": "complete", "properties": [{"name": "temperature", "state": "active", "code": null}]}]}status is complete, degraded or unavailable. Only Nodelets and properties the key may read the history of are listed.
Not covered here
Section titled “Not covered here”The dashboard uses routes under /account/ on the dashboard host with a signed-in session. They are not an API for programs and are not documented.