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.
Systems and serial numbers
Section titled “Systems and serial numbers”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.
Product families
Section titled “Product families”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
0kWh, 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.
Intervals and bucket boundaries
Section titled “Intervals and bucket boundaries”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.
Freshness and lag
Section titled “Freshness and lag”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.
latestIntervalisnullwhen the system produced no bucket in the last 24 hours.- A dashboard that shows “now” should use
stateOfChargeandconnectivity, 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.
Data availability
Section titled “Data availability”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 states
Section titled “Connectivity states”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.
Pagination
Section titled “Pagination”List endpoints take page (1-based) and pageSize, and return page, pageSize
and totalCount alongside items. pageSize is capped at 200. See
Pagination.