Read and correct a point's stored history. Exists primarily so Baler can act as a drop-in history-storage backend for Haxall/SkySpark's IHisExt extension point (span-based read, point-scoped read/write/delete) - see the "Haxall drop-in" doc page.
Read a point's stored history over a time span
Mirrors Haxall's IHisExt.read span semantics: start/end are
both optional and inclusive - omit both for the point's entire
history. Results are always ordered oldest-first.
query Parameters
pointSame raw topic/label POST /ingest uses - resolved to the same point identity internally.
startUnix epoch seconds, inclusive. Omit for the beginning of history.
endUnix epoch seconds, inclusive. Omit for the current time.
Read a point's stored history over a time span › Responses
Matching history items, oldest first. Empty array if the point has no history in range.
tsUnix epoch seconds.
Whatever type was originally stored.
qualityPresent only on a flagged sample (#183). The value is kept as received; fault rules and Cx checks skip flagged samples.
Delete one point's history item at an exact timestamp
The Baler side of Haxall's IHisExt.write delete convention (a written value equal to xeto::None.val means "remove this item", not "store null"). Deletes at most one row - the one at exactly this timestamp.
query Parameters
pointtsUnix epoch seconds, exact match.
Delete one point's history item at an exact timestamp › Responses
Deleted. No response body.
Axon-style `readAll(filter).hisRead(span)` - many points' history in one call
The SkySpark "what is this AHU doing?" query, against Baler's
own graph + history: a Haystack filter picks entities, hisRead
picks the span, an optional hisRollup folds the raw samples into
fixed buckets. Points that match are read directly; equipment
that matches is expanded to every point it brick:hasPoint (the
one deliberate departure from Axon, where hisRead on an equip is
an error) - so read(ahu).hisRead(today) is enough to see a whole
air handler. Rendered as charts by the demo UI at /ui/his.html.
Grammar (see hisquery.py for the full set of error messages):
Code
- filter: Haystack filter syntax -
ahu,air and temp and sensor,not vav,equipRef == @AHU-1,id == @urn:equip:fbf/ahu-1,kind == "Bool",temp > 72, parentheses. A name matches three ways at once, so Brick-typed data needs no Brick spelling: as a Haystack marker (haystack:hasTag); as a Brick class - case-insensitive, with every subclass and Brick alias folded in (Temperature_SensorfindsZone_Air_Temperature_Sensorpoints;AHU,Air_Handling_Unit,air_handling_unitall find air handlers and rooftop units); and as a Brick tag word, the words a class name is made of (temperature and sensor,zone and air and temp and sensor- Haystack spellingstemp,sp,cmd,equipare mapped). Hierarchy comes from the vendoredontology/Brick-only.ttl, so this works whether or not Brick is loaded into the graph.point/equip/sitealso match on graph structure, since BACnet-sourced entities never got those as explicit tags. Not supported:->tag paths, arithmetic, unit conversion. - span:
today,yesterday,thisWeek,lastWeek,pastWeek,thisMonth,lastMonth,pastMonth,thisQuarter,lastQuarter,thisYear,lastYear,pastYear(with or without()), a date2026-09-03, a month2026-09, a year2026, or a range2026-09-01..2026-09-07. Resolved intz; weeks start Monday. - rollup: fold is one of
avg,min,max,sum,count; interval is<n><unit>with unitsec,min,hr,day,wk,mo(1/3 only),yr. Booleans fold as 0/1; each bucket is stamped with its start.
query Parameters
exprThe query, as written above.
tzIANA zone the span is resolved in. Defaults to BALER_TZ, else UTC.
limitMax raw samples per point (ignored for rollups). Defaults to 10000, same as SkySpark's hisRead default; each series reports truncated: true if it hit this.
compact1: each series' history is two parallel arrays, {"ts": [...], "value": [...]}, instead of one {ts, value} object per sample - the same data in about half the bytes (Baler#107). Whole-second timestamps are integers. Omit for the default form.
Axon-style `readAll(filter).hisRead(span)` - many points' history in one call › Responses
One series per resolved point, each with its metadata and history for the span.
exprThe expression as received.
modefilterJust the filter part of the expression.
Present when the expression had a hisRollup; every series is then numeric and bucket-stamped.
limitThe per-point raw-sample cap that applied.
matchedURIs the filter matched (before equipment-to-point expansion), first 200.
matchedCountOnly ever non-empty when matchedCount is 0: filter names that
are almost a Brick class or tag word (Air_Handeling_Unit,
temperture), with the nearest real ones. Never an error -
the name may be a valid Haystack marker or PROJ class the
vendored Brick can't know about.

