Skip to main content

Resources

Now that we have a site, we can add flexible resources to it. This step is crucial for providing flexibility and enables our platform to accurately gauge activation rates, resulting in more activations for your resources. πŸš€

Types​

There's a long list of resources (devices, assets) that can be flexible, the most common ones are listed below.

The Powernaut platform is indifferent to the type of resource, meaning all types can be registered. However, the type of asset is a required data point to adequately activate flexibility.

  • Batteries
  • Electric Vehicles (EV)
  • Charging stations for EVs
  • Heat pumps
  • Solar panels
  • Electrical boilers
  • Windmill
  • Groups (beta) - Aggregated resources representing hybrid sites
  • Meters – Observational only: no bids, no activation. Useful to model loads or production that don't offer flexibility.
warning

A "head meter" is a special type of meter. It measures the total consumption or production of a site, but we don't expect you to create head meters as resources! It's enough to send head meter data over MQTT.

Managing​

Creating​

To create a new flexible resource, you need at least its site, type and power constraints.

import requests
import json

url = "https://api.powernaut.io/v1/connect/resources"

payload = json.dumps({
"site_id": "<uuid>",
"type": "electric_vehicle_charging_point",
"power": {
"active": {
"minimum": "0",
"maximum": "7.4"
}
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
Numbers

You'll notice that throughout the API, numbers are communicated with a string datatype, instead of the usual number. This is on purpose, and is done to avoid floating point errors. Number types will be rejected by the API.

Update​

You can also update a resource, e.g. update its name.

import requests
import json

url = "https://api.powernaut.io/v1/connect/resources/<uuid>"

payload = json.dumps({
"name": "Home Battery"
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}

response = requests.request("PATCH", url, headers=headers, data=payload)

print(response.text)

Delete​

Deleting a resource is done similarly to sites:

import requests

url = "https://api.powernaut.io/v1/connect/resources/<uuid>"

payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}

response = requests.request("DELETE", url, headers=headers, data=payload)

print(response.text)
warning

Deleting a resource is a permanent action and will delete all future flexibility. Ensure this is the intended action. The API will reject the creation of bids and baselines for resources that have been deleted.

In the case that a bid was selected for a procurement in the future, this bid will also be cancelled and the resource will not be activated.

Listing​

You can fetch a resource by its ID, or list all of them.

Listing all Resources​

import requests

url = "https://api.powernaut.io/v1/connect/resources"

payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)

Listing a Site's Resources​

import requests

url = "https://api.powernaut.io/v1/connect/resources"

payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)

Resource Groups​

Groups let you combine multiple physical resources into a single flexible unit for bidding. A group is a logical construct and has no meter data of its own. Members of a group activate together as a unit and their flexibility is aggregated into a single bid.

A group can be assigned to pools and activated, with its power and capacity values representing the aggregate across its members.

Creating Groups​

Groups are created as resources with type: "group". When creating a group, you must manually specify the power constraintsβ€”the platform does not automatically calculate these from group members.

  • Power constraints: Provide the combined import/export capability in kW using power.active.minimum (for export/consumption) and power.active.maximum (for import/production). These values represent the aggregate across all underlying assets.
  • Capacity (optional): If the group includes batteries, provide the total storage capacity in kWh using capacity.maximum.

All group members must belong to the same site.

Adding Members to Groups​

Add resources to a group by setting the group_id field when creating or updating a resource:

  • When creating a resource: include group_id in the request body
  • When updating a resource: set group_id to the group's identifier, or set it to null to remove a resource from its existing group

Behaviour​

  • Meter data is expected on the individual member resources, not the group itself β€” the group has no physical measurement point. Do not submit streaming data against the group's identifier.
  • Availability and overall status on the group are derived from its members. Individual members retain their own statuses.
  • Power and capacity constraints must be specified manually and updated when members are added or removed β€” the platform does not recalculate them automatically.

Resource Parents​

Resources in a site can be arranged into a physical topology tree β€” a hierarchy that reflects which meter a resource sits downstream of electrically. Think of it as the physical base layout of the site. Submetering relies on this hierarchy: it tells the platform which assets each intermediate meter covers, so their data can be handled correctly.

info

Groups are a separate, logical overlay on top of that layout. They bundle resources for flexibility bidding and have no interaction with the parent-child tree at all.

A typical use case is a site with a main meter at the grid connection point and several sub-meters beneath it, each measuring a distinct subset of generation or consumption. Only meter-type resources can be parents β€” the hierarchy models how meters are physically wired, not arbitrary resource relationships.

Set this relationship using the parent_id field on a resource.

Functional effects​

For most sites, setting parent_id is purely visual: it controls how the site layout is rendered in the portal, with no effect on bidding or activation.

The one functional exception is virtual head metering. When a site has infer_meter_data_from_resources enabled, the platform derives the head meter reading by summing meter data from resources at that site. Resources with a parent_id set are excluded from this sum β€” their parent meter is included instead, because the meter already physically measures everything downstream of it. Including both the meter and its children would double-count. If your site does not use virtual head metering, this has no effect.

How it differs from groups​

ConceptFieldPurposeStructure
Physical topologyparent_idElectrical layout, virtual meteringTree (up to 10 levels deep)
Logical groupinggroup_idBundle resources for flexibility biddingOne level (member β†’ group)

A non-group resource can have both a parent_id and a group_id at the same time β€” the two fields are independent. Group resources are outside the parent-child tree entirely: they cannot have a parent_id, and they cannot be set as the parent_id of another resource.

Setting a parent​

Set parent_id when creating or updating a resource. Set it to null to remove the relationship.

Rules​

  • Only meter-type resources can be a parent.
  • The parent must be on the same site as the resource.
  • A resource cannot be its own parent.
  • Cycles are not allowed. A cycle would mean resource A is an ancestor of B and B is an ancestor of A β€” equivalent to a meter being electrically both upstream and downstream of another meter at the same time, which is physically impossible.
  • The maximum depth is 10. Depth is the number of layers in the tree: a chain A β†’ B β†’ C has a depth of 3.
  • Group resources are outside the parent-child tree entirely. They cannot have a parent_id, and cannot be the parent_id of another resource.

Terminology​

Use parent / child for parent_id relationships. Use group / member for group_id relationships. The two concepts are distinct β€” a group member is not a "child" of its group.

Status​

We continuously monitor all resources through automated health checks. The status of all these health checks is aggregated into a single, high-level resource status, providing a quick overview of a resource's operational readiness.

StatusMeaning
onboardingThe resource has been added to the platform, but no meter data has been received yet.
operationalAll health checks are successful.
degradedSome health checks are failing. This causes suboptimal steering.
suspendedThe resource has failing health checks.

ℹ️ Note on a Future Update: For now, the statuses are purely informational to help you troubleshoot and resolve issues with your resources. In a future update, resources with status suspended will no longer be eligible to have their flexibility bids activated.

Health checks​

The Powernaut platform performs several health checks on each resource to ensure it's functioning properly and can deliver flexibility as promised.

Availability​

The availability health check monitors if the Powernaut platform is receiving meter data from the resource.

StatusMeaning
initialHealth check hasn't run yet.
onlineThe platform is receiving meter data.
offlineThe platform hasn't received any data for the past 15 minutes.

Activation compliance​

🚧 We are working to add this health check

The activation compliance health check monitors if resources are accurately delivering as much flex as was requested.

StatusMeaning
initialHealth check hasn't run yet.
compliantThe resource is delivering between 60-140% of the energy requested.
not_compliantDelivered energy deviates more than 40% from the energy requested for 4 consecutive quarter hours.

Baselines too inaccurate​

🚧 We are working to add this health check

This health check monitors the accuracy of the baselines for your site and resources. Without accurate baselines we cannot verify the delivered flexibility accurately.

Keep the following in mind:

  • For connection points, baselines need to be accurate even when their individual resources are not bidding, as they might be part of a larger pool that is being balanced.
  • You can update baselines for any resource on a connection point up until the moment the first resource on that connection point gets activated. We encourage you to take full advantage of this window to finalise your baselines for maximum accuracy and fair settlement.
StatusMeaning
initialHealth check hasn't run yet.
accurateBaseline is accurate.
inaccurateNormalised MAE* of corresponding site's baseline is larger than 0.75 for over 1 day.

* MAE stands for Mean Absolute Error. This is the average of the difference between the baseline and actual meter data. We normalise MAE by dividing by the average absolute consumption.

No Bids​

🚧 We are working to add this health check

This health check monitors the bids made by a resource. If a resource has not made any bids for a long time, something is probably wrong. To see how we expect resources to bid have a look at our examples.

StatusMeaning
initialHealth check hasn't run yet.
activeResource is actively making bids.
no_bidsResource has not made any bids for a longer period.

When we flag resources for not bidding depends on the resource type:

  • Solar Panels: after 1 day
  • Batteries: after 1 day
  • Electric Vehicles: after 5 days

Meter data anomalies​

🚧 We are working to add this health check

This health check monitors if resources submit weird meter data.

StatusMeaning
initialHealth check hasn't run yet.
okResource has logged meter data correctly.
rare_anomalyLess than 1% of meter data is outside of bounds in the last 1 day.
frequent_anomalyMore than 1% of meter data is outside of bounds in the last 1 day.