DUET PlatformDocs
API referenceRead APIPerformance

List loss events

available
GET
/platform/v1/loss-events

Authorization

Bearer
headerAuthorizationBearer <token>

Query Parameters

project_id*string

The DUET project ID. You must have access to the project.

dt_start*string

The first date to include, in ISO 8601 format, for example 2026-05-25.

dt_end*string

The last date to include, in ISO 8601 format, for example 2026-05-31.

sentinel_tag?string

The deployment tag. Most projects have one deployment, default. A project with several data streams can name a specific deployment.

Default"default"
group_by*string

How to group the rows:

  • asset: one row for each inverter, asset, and label. A component that spans inverters, such as a tracker, gets one row for each affected inverter. The Investigate residual is also split by inverter.
  • inverter: one row for each inverter and label.
  • block: one row for each block and label.
  • label: one row for each label, rolled up across the site.
Value in"asset""inverter""block""label"
labels_include?array<string>

Return only these labels. Repeat the parameter for each label, for example ?labels_include=Investigate&labels_include=Combiner+Outage. Accepts display labels or raw labels.

labels_exclude?array<string>

Leave out these labels. Repeat the parameter for each label. Accepts display labels or raw labels. By default, DUET leaves out Grid Curtailment. To include it, pass your own labels_exclude list or list Grid Curtailment in labels_include.

inverter_ids_include?array<string>

Return only these inverters. The values match the inverter_id field on response rows. Repeat the parameter for each ID.

inverter_ids_exclude?array<string>

Leave out these inverters. Repeat the parameter for each ID.

loss_wh_gt?|

Leave out rows where abs(attributed_loss_wh) is less than or equal to this value, in watt-hours.

loss_wh_lt?|

Leave out rows where abs(attributed_loss_wh) is greater than or equal to this value, in watt-hours.

limit?integer

The maximum number of rows to return. The default is 10,000 and the maximum is 100,000. If you receive exactly limit rows, more rows might exist. To get them, increase offset by limit and call again.

Range1 <= value <= 100000
Default10000
offset?|

The zero-based number of rows to skip. Use it with limit to page through large results.

Range0 <= value
Default0

Header Parameters

Accept?string
Default"application/vnd.apache.arrow.stream"
Value in"application/vnd.apache.arrow.stream""application/vnd.apache.parquet""application/json-seq"

Response Body

A stream of loss-event rows, one for each group_by key. The Accept header sets the format: an Arrow IPC stream (the default), Parquet, or JSON-seq, which is newline-delimited JSON objects.

Each row carries attributed_loss_wh (less than or equal to 0), attributed_gain_wh (greater than or equal to 0), and attributed_delta_wh (the signed sum). Summed across rows, the signed sum matches the per-label waterfall total.

  1. response
project_id*string

The project ID from the request. Every row has the same value.

label*string

The display form of the loss label, for example Investigate, Combiner Outage, or Tracker Controller Fault. Investigate covers the unclassified residual and any catch-all classifier output.

inverter_id*|

The stable ID of the inverter, which is the AC-power asset that the loss flowed through. It's a DUET composite ID, typically {block_uuid}-inverter-{n}. Set when group_by is asset or inverter. Null otherwise.

inverter_name*|

The inverter's display name, for example Feeder-12-Inverter-09.

inverter_sensor_tag*|

The SCADA sensor tag of the inverter. Use it to look up the inverter itself, rather than the asset that the label is attached to.

asset_id*|

The stable ID of the asset that the loss is attributed to: a combiner for Combiner Outage, a tracker for Tracker Stuck, and the inverter itself for inverter-level labels and Investigate. It's a DUET composite ID, for example {block_uuid}-inverter-6-combiner-9. Equals inverter_id when the label is attached at the inverter level. Set when group_by is asset. Null otherwise.

asset_name*|

The asset's display name, for example Feeder-09-Tracker-Controller-1.

sensor_tag*|

The SCADA sensor tag of the asset. Use it to find the asset in your monitoring system. Equals inverter_sensor_tag when the label is attached at the inverter level.

duet_block_id*|

The ID of the block that the row belongs to. Set when group_by is block. Also set when group_by is asset or inverter and the block is unambiguous.

active_duration_seconds*number

The total time, in seconds, during which the group had non-zero attribution. Use this field for duration. Don't use max_ts minus min_ts, which is the range that the group's events covered, including gaps.

attributed_loss_wh*number

The attribution clamped to negative values, in watt-hours. Always less than or equal to 0. It's the loss caused by this group. The sum of abs(attributed_loss_wh) adds up correctly across any grouping.

attributed_gain_wh*number

The attribution clamped to positive values, in watt-hours. Always greater than or equal to 0, and typically near 0. A non-zero value means the meter exceeded the model during a classified period. This reflects model noise, not asset overperformance.

attributed_delta_wh*number

The signed sum, in watt-hours. Summed across rows, it matches the per-label waterfall total. attributed_loss_wh + attributed_gain_wh always equals attributed_delta_wh.

min_ts*string

The earliest time at which the group had non-zero attribution. Format: YYYY-MM-DD HH:MM:SS, in site-local time, with no time zone.

max_ts*string

The latest time at which the group had non-zero attribution. Format: YYYY-MM-DD HH:MM:SS, in site-local time, with no time zone. The interval from min_ts to max_ts is the range, not the active duration. For the active duration, use active_duration_seconds.

Example Request
curl -X GET 'https://api.enurgen.com/platform/v1/loss-events?project_id=string&dt_start=string&dt_end=string&group_by=asset'
Example Response
{  "project_id": "string",  "label": "string",  "inverter_id": "string",  "inverter_name": "string",  "inverter_sensor_tag": "string",  "asset_id": "string",  "asset_name": "string",  "sensor_tag": "string",  "duet_block_id": "string",  "active_duration_seconds": 0,  "attributed_loss_wh": 0,  "attributed_gain_wh": 0,  "attributed_delta_wh": 0,  "min_ts": "string",  "max_ts": "string"}