Powoflow API reference
Base URL: https://api.powoflow.com. Every route below, and nothing else, can be reached with an API key. The same reference as OpenAPI 3.1: /v1/openapi.json.
Authentication
Send an API key with every request: Authorization: Bearer <key>. An administrator of your organization creates keys in Settings → API keys. A key reads only its own organization's data. Read-only keys read; read-write keys, on paid plans, can also create work orders and comments. Keep keys secret: anyone with one acts as your organization. API keys aren't available in workspaces that may hold patient data.
Times, units and pages
Times are Unix milliseconds (ts, from, to) or ISO 8601 strings (updatedAt, createdAt, dates). One telemetry request covers at most 7 days. Every reading carries its own unit, exactly as the sensor reported it: the API converts nothing. Lists come a page at a time: pass back cursor (or nextCursor) for the next page. A field with no value is left out or null, never a made-up zero.
Rate limits
Per organization, per minute: 60 calls on the Free plan, 600 on paid plans. Telemetry reads (/telemetry and /telemetry/latest) also count against their own 30 a minute. Over a limit the answer is 429 RATE_LIMITED with a Retry-After header in seconds.
Errors
An error answers {"error": {"code": …, "message": …}}. Branch on the code; the message is for people.
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_REQUEST | A query parameter or body field is not one this route takes, or a value is not valid. |
| 400 | RANGE_TOO_LARGE | A telemetry request covers more than 7 days. Split a longer range into several requests. |
| 401 | UNAUTHORIZED | No API key, or one that is not valid, expired or revoked. Every way a key can be wrong gets this same answer. |
| 403 | READ_ONLY | This key, or the organization's plan, can read but not write. |
| 403 | PLAN_NO_API_ACCESS | The organization's plan does not include API access. |
| 403 | TENANT_INACTIVE | The organization is not active. |
| 403 | PHI_BLOCKED | API keys aren't available in workspaces that may hold patient data. |
| 403 | REQUEST_REFUSED | The request was refused. The message says why. |
| 404 | NOT_FOUND | No such route, or no such item in your organization. The two are not told apart. |
| 429 | RATE_LIMITED | Too many requests this minute. Wait the number of seconds in the Retry-After header. |
| 502 | UPSTREAM_ERROR | The request could not be completed. It is safe to retry a read. |
| 503 | UNAVAILABLE | A temporary problem. Retry after the seconds in the Retry-After header. |
Routes
GET/v1/resources
List resources. Your organization's resources (sites, buildings, devices, sensors and the rest), a page at a time.
Key: read-only or read-write.
| Field | In | What |
|---|---|---|
limit | query | The most items in one page. The answer's count says how many came back. |
cursor | query | The cursor (or nextCursor) from the previous page, to read the next one. Leave it out for the first page. |
resourceClass | query | Only resources of this class, e.g. SITE or PHYSICAL_ASSET. |
resourceTypeId | query | Only resources of this type. |
parentResourceId | query | Only the direct children of this resource. |
status | query | Only resources in this status, e.g. active. |
updatedSince | query | Only resources changed since this time: Unix milliseconds or an ISO 8601 time. |
Answer fields: items, count, cursor; each item: resourceId, resourceName, resourceClass, resourceTypeName, status, lifecycleStatus, criticality, parentResourceId, updatedAt
curl "https://api.powoflow.com/v1/resources?resourceClass=SITE&limit=50" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"count": 1,
"cursor": null,
"items": [
{
"resourceClass": "SITE",
"resourceId": "res-01EXAMPLESITE0000000000000",
"resourceName": "North Yard",
"status": "active",
"updatedAt": "2026-11-10T09:00:00.000Z"
}
]
}GET/v1/resources/{resourceId}
Get a resource. One resource of your organization.
Key: read-only or read-write.
| Field | In | What |
|---|---|---|
resourceId | path | The resource's id (res-…), from GET /v1/resources. |
Answer fields: resourceId, resourceName, resourceClass, resourceTypeName, status, lifecycleStatus, criticality, parentResourceId, updatedAt
curl "https://api.powoflow.com/v1/resources/res-01EXAMPLEPUMP0000000000000" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"criticality": "high",
"parentResourceId": "res-01EXAMPLESITE0000000000000",
"resourceClass": "PHYSICAL_ASSET",
"resourceId": "res-01EXAMPLEPUMP0000000000000",
"resourceName": "Pump 2",
"resourceTypeName": "Pump",
"status": "active",
"updatedAt": "2026-11-10T09:00:00.000Z"
}GET/v1/resources/{resourceId}/telemetry
Read a sensor's readings. A sensor's readings over a time range, newest first unless order=asc, downsampled to about targetPoints points when there are more. Each point carries its own unit, exactly as recorded.
Key: read-only or read-write. Counts against the telemetry limit too.
| Field | In | What |
|---|---|---|
resourceId | path | The sensor's id: a resource whose readings you want. |
from | query | The start of the range, in Unix milliseconds. |
to | query | The end of the range, in Unix milliseconds. Defaults to now. |
limit | query | The most items in one page. The answer's count says how many came back. |
order | query | asc for oldest first. Newest first otherwise. |
cursor | query | The cursor (or nextCursor) from the previous page, to read the next one. Leave it out for the first page. |
targetPoints | query | About how many points to return over the range: more readings than this are downsampled, each point then carrying its bucket's min, max and count. |
Answer fields: count, downsampled, totalPoints, targetPoints, bucketMs, pointsCapped, truncated, hasMore, cursor, nextCursor, items; each item: ts, value, min, max, minTs, maxTs, count, unit, valueType
curl "https://api.powoflow.com/v1/resources/res-01EXAMPLETEMP0000000000000/telemetry?from=1762761600000&to=1762765200000&order=asc" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"count": 1,
"downsampled": false,
"hasMore": false,
"items": [
{
"ts": 1762761600000,
"unit": "°C",
"value": 4.5,
"valueType": "AirTemperature"
}
],
"nextCursor": null
}GET/v1/resources/{resourceId}/telemetry/latest
Read a sensor's latest reading. A sensor's newest reading. latest is null when it has none.
Key: read-only or read-write. Counts against the telemetry limit too.
| Field | In | What |
|---|---|---|
resourceId | path | The sensor's id. |
Answer fields: resourceId, latest
curl "https://api.powoflow.com/v1/resources/res-01EXAMPLETEMP0000000000000/telemetry/latest" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"latest": {
"ts": 1762765200000,
"unit": "°C",
"value": 4.7,
"valueType": "AirTemperature"
},
"resourceId": "res-01EXAMPLETEMP0000000000000"
}GET/v1/resources/{resourceId}/alarms
List a resource's alarms. The alarm rules on one resource, with their current state.
Key: read-only or read-write.
| Field | In | What |
|---|---|---|
resourceId | path | The resource's id (res-…), from GET /v1/resources. |
Answer fields: items, count, truncated; each item: alarmId, name, severity, currentState, resourceId, resourceName, resourceClass, lastStateChange, createdAt, acknowledgedAt
curl "https://api.powoflow.com/v1/resources/res-01EXAMPLEPUMP0000000000000/alarms" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"count": 1,
"items": [
{
"alarmId": "alm-01EXAMPLE00000000000000000",
"currentState": "NORM",
"lastStateChange": "2026-11-09T22:10:00.000Z",
"name": "Pump 2 high temperature",
"resourceId": "res-01EXAMPLEPUMP0000000000000",
"severity": "high"
}
]
}GET/v1/alarms/active
List active alarms. Your organization's alarms that are active now, worst first.
Key: read-only or read-write.
Answer fields: items, count, truncated; each item: alarmId, name, severity, currentState, resourceId, resourceName, resourceClass, lastStateChange, createdAt, acknowledgedAt
curl "https://api.powoflow.com/v1/alarms/active" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"count": 1,
"items": [
{
"alarmId": "alm-01EXAMPLE00000000000000000",
"currentState": "UNACK",
"name": "Pump 2 high temperature",
"resourceId": "res-01EXAMPLEPUMP0000000000000",
"resourceName": "Pump 2",
"severity": "high"
}
],
"truncated": false
}GET/v1/alarms/summary
Count alarms. Your organization's alarms counted by state and by severity.
Key: read-only or read-write.
Answer fields: byState, bySeverity, total, active
curl "https://api.powoflow.com/v1/alarms/summary" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"active": 1,
"bySeverity": {
"high": 1
},
"byState": {
"NORM": 11,
"UNACK": 1
},
"total": 12
}GET/v1/alarms/{alarmId}
Get an alarm. One alarm rule of your organization, with its current state.
Key: read-only or read-write.
| Field | In | What |
|---|---|---|
alarmId | path | The alarm's id (alm-…). |
Answer fields: alarmId, name, severity, currentState, resourceId, resourceName, resourceClass, lastStateChange, createdAt, acknowledgedAt
curl "https://api.powoflow.com/v1/alarms/alm-01EXAMPLE00000000000000000" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"alarmId": "alm-01EXAMPLE00000000000000000",
"createdAt": "2026-10-01T08:00:00.000Z",
"currentState": "NORM",
"name": "Pump 2 high temperature",
"resourceId": "res-01EXAMPLEPUMP0000000000000",
"severity": "high"
}GET/v1/work-orders
List work orders. Your organization's work orders, a page at a time.
Key: read-only or read-write.
| Field | In | What |
|---|---|---|
limit | query | The most items in one page. The answer's count says how many came back. |
cursor | query | The cursor (or nextCursor) from the previous page, to read the next one. Leave it out for the first page. |
status | query | Only work orders in this status. |
priority | query | Only work orders of this priority. |
updatedSince | query | Only work orders changed since this time: Unix milliseconds or an ISO 8601 time. |
workOrderType | query | Only work orders of this type. |
Answer fields: items, count, cursor; each item: workOrderId, workOrderNumber, workOrderTitle, workOrderStatus, status, priority, workOrderType, resourceId, resourceName, dueDate, updatedAt, createdAt
curl "https://api.powoflow.com/v1/work-orders?status=open&limit=25" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"count": 1,
"cursor": null,
"items": [
{
"dueDate": "2026-11-14",
"priority": "high",
"resourceId": "res-01EXAMPLEPUMP0000000000000",
"status": "open",
"workOrderId": "wo-01EXAMPLE000000000000000000",
"workOrderNumber": "WO-2026-0042",
"workOrderTitle": "Replace pump seal"
}
]
}GET/v1/work-orders/{woId}
Get a work order. One work order of your organization.
Key: read-only or read-write.
| Field | In | What |
|---|---|---|
woId | path | The work order's id, workOrderId in the list. |
Answer fields: workOrderId, workOrderNumber, workOrderTitle, workOrderStatus, status, priority, workOrderType, resourceId, resourceName, dueDate, updatedAt, createdAt, description, category, startDate, completedAt
curl "https://api.powoflow.com/v1/work-orders/wo-01EXAMPLE000000000000000000" \ -H "Authorization: Bearer $POWOFLOW_API_KEY"
{
"createdAt": "2026-11-10T07:30:00.000Z",
"description": "Seal weeping at the shaft.",
"priority": "high",
"resourceId": "res-01EXAMPLEPUMP0000000000000",
"status": "open",
"workOrderId": "wo-01EXAMPLE000000000000000000",
"workOrderNumber": "WO-2026-0042",
"workOrderTitle": "Replace pump seal"
}POST/v1/work-orders
Create a work order. Opens a work order on one of your organization's resources. Needs a read-write key.
Key: read-write.
| Field | In | What |
|---|---|---|
workOrderTitle | body | What needs doing, in a few words. |
resourceId | body | The resource it is for: one of your organization's. |
description | body | More detail. |
priority | body | Its priority, e.g. low, medium, high. |
category | body | Its category. |
workOrderType | body | Its type, e.g. corrective or preventive. |
dueDate | body | When it is due (ISO 8601 date). |
startDate | body | When work starts (ISO 8601 date). |
estimatedHours | body | The estimated hours of work. |
Answer fields: workOrderId, workOrderNumber
curl -X POST "https://api.powoflow.com/v1/work-orders" \
-H "Authorization: Bearer $POWOFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"workOrderTitle":"Replace pump seal","resourceId":"res-01EXAMPLEPUMP0000000000000","priority":"high","dueDate":"2026-11-14"}'{
"workOrderId": "wo-01EXAMPLE000000000000000000",
"workOrderNumber": "WO-2026-0042"
}POST/v1/work-orders/{woId}/comments
Comment on a work order. Adds a comment to a work order. Needs a read-write key.
Key: read-write.
| Field | In | What |
|---|---|---|
woId | path | The work order's id. |
message | body | The comment's text. |
Answer fields: commentId, createdAt
curl -X POST "https://api.powoflow.com/v1/work-orders/wo-01EXAMPLE000000000000000000/comments" \
-H "Authorization: Bearer $POWOFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message":"Seal replaced, running normally."}'{
"commentId": "cmt-01EXAMPLE00000000000000000",
"createdAt": "2026-11-10T11:05:00.000Z"
}