Skip to content

Concepts

Read this before you build a chart or a threshold. The numbers are simple, but what they do and do not promise is not obvious.

A system is one Clayton Power power unit. Systems are addressed by serialNumber, the modem serial printed on the unit and shown in fleet-manager. It is the only identifier the External API accepts; internal database identifiers are never exposed and are not stable across our releases.

Treat the serial as an opaque string. Do not parse it, and do not assume it is numeric.

A serial that does not exist, and a serial that belongs to another company, are both answered with 404. See Company reach.

Systems belong to a product family, reported as family on the system object (for example LPS or E-GEN).

The family matters for one reason: it decides which energy numbers exist.

  • Energy (mainsKwh, solarKwh, vehicleKwh, totalKwh, consumptionKwh) is derived from the cumulative energy meters that the E-GEN firmware scheme reports. The platform reads the meter’s increase over each bucket.
  • Units that only report the older LPS channels do not carry those meters. Those channels carry an instantaneous current, not energy, so they contribute zero to every energy figure. For such a system the energy endpoints return 0 kWh, not an error and not null.
  • State of charge is read across both schemes, so a unit that changed family mid-range still produces one continuous SoC series. SoC is available where the energy figures are not.

If you get a flat zero energy series for a system that is plainly working, that is what you are looking at. GET /systems/{serialNumber}/telemetry/soc and .../telemetry/latest still return useful data, and platform@claytonpower.com can confirm what a given unit reports.

Quantity Unit Field suffix Notes
Energy kilowatt hour Kwh Energy moved during a bucket, not a running total
Power watt W Instantaneous
State of charge percent Percent 0 to 100
Time ISO 8601, UTC At, start, from, to Always with a trailing Z

Energy values are per bucket. Summing a channel across a range gives the total for that range. They are not odometer readings, so a bucket never carries a value from a previous period.

totalKwh on the input object is mainsKwh + solarKwh + vehicleKwh, summed from the same three values you receive, so it always adds up exactly.

vehicleKwh is the DC input from the vehicle’s alternator.

peakOutputW is the highest AC output power seen during the bucket. It is null when the bucket holds no peak-power measurement at all. null means “not measured”; it does not mean zero watts.

Series endpoints take an interval of 15m, 1h or 1d.

Buckets are aligned to UTC and half-open: a point whose start is S covers [S, S + width). A 1d bucket runs from UTC midnight to UTC midnight, regardless of where the system is or which time zone you are in. If your reporting day is local, do the shifting on your side; requesting 1h buckets and grouping them yourself is the usual approach.

Range limits, per request:

Interval Maximum range
15m 31 days
1h 366 days
1d 366 days

A range beyond the limit is rejected with 400 and errorCode = ValidationFailed. Split the period into several requests.

to defaults to now and from defaults to to - 24h.

Missing buckets are omitted. The series is not gap-free and never promises to be: a system that was switched off produces no rows for that period, and the response simply has no point with that start. Do not assume points[n+1].start is one interval after points[n].start. If you need a dense series, fill the gaps yourself from the interval width.

A bucket can also legitimately read 0 for an energy channel. Implausible readings are dropped by a guard on the read path, so a bucket that the upstream aggregation polluted comes back as zero rather than as a spike.

Different fields have different ages, and mixing them up produces charts that look broken.

Field Freshness
connectivity.lastSeenAt Refreshed about once a minute
stateOfCharge in /telemetry/latest Minute-fresh from the device status, falling back to the latest hourly bucket when the device has not reported one
latestInterval in /telemetry/latest The most recent completed 15-minute bucket, typically 15 to 30 minutes behind now
Energy and SoC series Same aggregation as latestInterval
health Assessed daily

The aggregation behind the 15-minute buckets refreshes every 15 minutes and leaves the most recent 15 minutes alone while they are still filling. A bucket that has just closed can therefore take 15 to 30 minutes to appear. This is normal and is not a sign that a system is offline.

Consequences worth designing for:

  • The bucket currently filling is never returned. Do not treat its absence as a gap.
  • latestInterval is null when the system produced no bucket in the last 24 hours.
  • A dashboard that shows “now” should use stateOfCharge and connectivity, which are minute-fresh, and label the energy figures with their bucket start.
  • Polling the series endpoint more often than every few minutes returns the same points. Poll every 15 minutes at most, or use webhooks for events.

Each system carries dataAvailableFrom, the earliest moment the platform holds data for it. It is typically the system’s start date with your company.

A from earlier than dataAvailableFrom is clamped up to it rather than rejected, so a request for “everything” is safe: send a from well in the past and you get the full history that exists. The from echoed in the response tells you what was actually used.

There is no data before dataAvailableFrom, including from a previous owner of the same unit.

connectivity.status in /telemetry/latest is derived from lastSeenAt:

Status Meaning
online Seen less than 5 minutes ago
stale Seen less than 30 minutes ago, but more than 5
offline Not seen for 30 minutes or more
unknown Never seen; the platform has no status row for this system

stale is normal for a unit in a vehicle: mobile coverage drops and returns. Do not alarm on it.

unknown is not offline. It means the system has never reported, usually because it has not been commissioned yet.

These thresholds are fixed and are separate from the alert thresholds you configure. The system.offline alert uses its own offlineAfterMinutes setting, which defaults to 30 minutes and can be changed per system. See Alerts.

List endpoints take page (1-based) and pageSize, and return page, pageSize and totalCount alongside items. pageSize is capped at 200. See Pagination.