Grouped Forecasting.
Forecast a set of related series that combine into a total, such as MRR by plan and region, demand by warehouse, or revenue by category. You receive one coherent result: every parent equals the sum of its children, in every period, at every level.
How it works
You send the leaves of your hierarchy. The leaves are every combination of the dimensions that you declare, each with its own history. The API then sums the leaf histories to derive every aggregate level, such as each region and the grand total. The API forecasts the nodes, reconciles them to coherence, and stores each node as its own entity with independently tracked accuracy.
The run is asynchronous. When you submit a hierarchy, the API returns
202 with an id to poll, and the run executes in the background as one all-or-nothing job.
A hierarchy is one coherent answer, so there is no partial success. If any node cannot be forecast,
the run fails with the reason. It does not return numbers that do not sum correctly.
Submit a hierarchy
The identifier names the measure. Each series carries a structured
segment that names exactly the declared hierarchy dimensions. segment is
independent of tenant_context. Tenancy still means "whose data is this", and
segment means "which slice".
{
"identifier": "mrr",
"hierarchy": ["region", "plan"],
"reconciliation": "bottom_up",
"frequency": "M",
"periods": 6,
"data_type": "revenue",
"series": [
{"segment": {"region": "eu", "plan": "pro"},
"data": [{"date": "2024-01-01", "value": 42000}, {"date": "2024-02-01", "value": 43800}]},
{"segment": {"region": "eu", "plan": "free"},
"data": [{"date": "2024-01-01", "value": 3100}, {"date": "2024-02-01", "value": 3300}]},
{"segment": {"region": "us", "plan": "pro"},
"data": [{"date": "2024-01-01", "value": 61000}, {"date": "2024-02-01", "value": 62500}]}
]
}
{
"grouped_forecast_id": "k3n9x2m4p8q1w5r7",
"status": "pending",
"series_count": 3,
"node_count": 6,
"reconciliation": "bottom_up",
"time_taken_ms": 41.2
}
node_count is the number of nodes that the API forecasts and reconciles. It counts the
leaves plus every derived aggregate and the total. The three series above expand to six nodes:
total, two regions, and three leaves. A request may expand to at most 250 nodes.
Poll for the result
This endpoint returns the run status. When the run is completed, it also returns a node
map keyed by segment (total, region=eu, plan=pro|region=eu, …).
Every node carries its own forecast rows, its place in the tree, and the reconciliation details.
{
"grouped_forecast_id": "k3n9x2m4p8q1w5r7",
"status": "completed",
"node_count": 6,
"results": {
"identifier": "mrr",
"hierarchy": ["region", "plan"],
"reconciliation": {"method": "bottom_up", "correlation": 0.5, "correlation_source": "default", "measured": false},
"confidence_level": 0.8,
"nodes": {
"total": {
"segment": {},
"parent": null,
"children": ["region=eu", "region=us"],
"forecasts": [{"period": 1, "date": "2024-07-01", "forecast": 118400.0, "lower": 112300.5, "upper": 124499.5}]
},
"region=eu": {
"segment": {"region": "eu"},
"parent": "total",
"children": ["plan=free|region=eu", "plan=pro|region=eu"],
"forecasts": [{"period": 1, "date": "2024-07-01", "forecast": 51900.0, "lower": 48700.2, "upper": 55099.8}]
}
}
}
}
Reconciliation methods
model_info.reconciliation.base_forecast.Confidence bands on aggregates
Summing the children's lower values is not a lower bound for the parent. That sum
assumes every child misses low at once. With bottom_up, the API instead builds an
aggregate band from its children's uncertainties under a stated correlation assumption between sibling
errors (correlation, default 0.5, overridable per request between 0 and 1). The response
echoes this assumption and never labels it as measured. With min_trace, each node
keeps its own band, re-centered on the reconciled point with its width preserved.
model_info.reconciliation.interval_reason. This is an honest
absence rather than a decorative interval.Rules and limits
- Every series must declare exactly the hierarchy dimensions in its
segment, and each combination may appear once. - All series must end on the same date so the forecast periods align. A history may start at any date. A segment that launched later contributes zero before its first data point.
periods,frequency,modelandconfidenceare request-level only. Every node of a hierarchy must share them, so the API rejects per-series overrides instead of ignoring them silently. For the same reason, the API does not acceptmodel: autohere. It routes per series, and the API reconciles a hierarchy under one model.- Up to 4 hierarchy levels and 250 expanded nodes per request (10 leaf series on the free plan).
- Grouped forecasts do not yet support
quantiles,value_bounds,adjustmentsandaccumulate. The API rejects them explicitly.
tenant_context. It is simpler and tolerates per-series failure. See
Patterns & Segmentation.