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.

StatusCodeMeaning
400INVALID_REQUESTA query parameter or body field is not one this route takes, or a value is not valid.
400RANGE_TOO_LARGEA telemetry request covers more than 7 days. Split a longer range into several requests.
401UNAUTHORIZEDNo API key, or one that is not valid, expired or revoked. Every way a key can be wrong gets this same answer.
403READ_ONLYThis key, or the organization's plan, can read but not write.
403PLAN_NO_API_ACCESSThe organization's plan does not include API access.
403TENANT_INACTIVEThe organization is not active.
403PHI_BLOCKEDAPI keys aren't available in workspaces that may hold patient data.
403REQUEST_REFUSEDThe request was refused. The message says why.
404NOT_FOUNDNo such route, or no such item in your organization. The two are not told apart.
429RATE_LIMITEDToo many requests this minute. Wait the number of seconds in the Retry-After header.
502UPSTREAM_ERRORThe request could not be completed. It is safe to retry a read.
503UNAVAILABLEA 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.

FieldInWhat
limitqueryThe most items in one page. The answer's count says how many came back.
cursorqueryThe cursor (or nextCursor) from the previous page, to read the next one. Leave it out for the first page.
resourceClassqueryOnly resources of this class, e.g. SITE or PHYSICAL_ASSET.
resourceTypeIdqueryOnly resources of this type.
parentResourceIdqueryOnly the direct children of this resource.
statusqueryOnly resources in this status, e.g. active.
updatedSincequeryOnly 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.

FieldInWhat
resourceIdpathThe 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.

FieldInWhat
resourceIdpathThe sensor's id: a resource whose readings you want.
fromqueryThe start of the range, in Unix milliseconds.
toqueryThe end of the range, in Unix milliseconds. Defaults to now.
limitqueryThe most items in one page. The answer's count says how many came back.
orderqueryasc for oldest first. Newest first otherwise.
cursorqueryThe cursor (or nextCursor) from the previous page, to read the next one. Leave it out for the first page.
targetPointsqueryAbout 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.

FieldInWhat
resourceIdpathThe 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.

FieldInWhat
resourceIdpathThe 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.

FieldInWhat
alarmIdpathThe 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.

FieldInWhat
limitqueryThe most items in one page. The answer's count says how many came back.
cursorqueryThe cursor (or nextCursor) from the previous page, to read the next one. Leave it out for the first page.
statusqueryOnly work orders in this status.
priorityqueryOnly work orders of this priority.
updatedSincequeryOnly work orders changed since this time: Unix milliseconds or an ISO 8601 time.
workOrderTypequeryOnly 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.

FieldInWhat
woIdpathThe 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.

FieldInWhat
workOrderTitlebodyWhat needs doing, in a few words.
resourceIdbodyThe resource it is for: one of your organization's.
descriptionbodyMore detail.
prioritybodyIts priority, e.g. low, medium, high.
categorybodyIts category.
workOrderTypebodyIts type, e.g. corrective or preventive.
dueDatebodyWhen it is due (ISO 8601 date).
startDatebodyWhen work starts (ISO 8601 date).
estimatedHoursbodyThe 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.

FieldInWhat
woIdpathThe work order's id.
messagebodyThe 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"
}