Models & Limits
The API serves one model: SequenxAI Omni, SequenxAI's general time-series model, with the model id hora-1.0. It is used when model is omitted. The floating alias hora points to the same model; responses always name the concrete id in model_used (hora-1.0). The server checks a request against the limits below before cleaning or inference.
1. Limits
| Model | Min context | Max context | Max horizon h |
|---|---|---|---|
hora-1.0 | 16 | 4,096 | 1,024 |
The forecast span is h times the data frequency, so the same limit covers different lengths of time at different frequencies: with 15-minute data, a request allows at most 1,024 steps (about 10.7 days); with hourly data, about 42.7 days.
The limits come from the model service's capability list, which the server refreshes about once a minute; while that list is unreachable the server uses its built-in copy. If a limit changes, the numbers in error responses win: details.max_horizon on HORIZON_EXCEEDS_MODEL, details.max_context on SERIES_TOO_LONG, and min_context on the too_short_for_model entry of the cleaning report.
2. How the limits apply
| Limit | Behavior |
|---|---|
| Max horizon | An h above the limit returns 422 HORIZON_EXCEEDS_MODEL right away: no cleaning, no quota used. h is also bound by the contract's 1–2048. |
| Max context | An entity longer than the limit returns 422 SERIES_TOO_LONG; history is never cut for you. It is measured per unique_id on what the model would receive: distinct timestamps before cleaning, then the regular grid after cleaning (filled slots count), or rows under raw. An entity with a gap at or above the segment-split threshold (options.gap_split_min_steps) passes the first check, because cleaning may keep only its latest segment; the grid after cleaning decides. Nothing is billed. Send only the most recent points. |
| Min context | If an entity has fewer points than the limit after cleaning (imputed points included), the call returns 422 SERIES_TOO_SHORT. |
{
"error": {
"code": "HORIZON_EXCEEDS_MODEL",
"message": "h=1500 exceeds the maximum horizon 1024 of model 'hora-1.0'",
"request_id": "req_…",
"details": {"model": "hora-1.0", "h": 1500, "max_horizon": 1024}
}
}{
"error": {
"code": "SERIES_TOO_LONG",
"message": "A series is longer than the maximum context of model 'hora-1.0' (4096 points); send only the most recent 4096 points per series",
"request_id": "req_…",
"details": {
"model": "hora-1.0", "max_context": 4096, "measured": "timestamps",
"series": [{"unique_id": "meter-001", "points": 8760}], "series_count": 1,
"hint": "Send only the most recent 4096 points of each listed series"
}
}
}3. Model options
The optional model_options object switches inference behavior. Both keys are optional; omitted keys use their defaults. It applies to /v1/forecast only (/v1/clean runs no model).
| Key | Values | Default | Behavior |
|---|---|---|---|
nonnegative | "auto", true, false | "auto" | "auto": the forecast of an entity (y_hat and interval bounds) is clamped at 0 only when all of that entity's history fed to the model is non-negative. true: always clamp at 0. false: never clamp. |
flip_average | true, false | true | true: the model also forecasts the negated history and averages it (mirrored back) with the direct forecast. This takes about twice the inference compute and may add latency. false: a single pass. |
Billing does not depend on these options: it stays per forecast point, so flip_average: true costs the same as false. nonnegative here acts on the forecast; it is unrelated to options.cleaning.nonnegative, which only constrains imputed history values.
{
"model": "hora-1.0",
"series": [ … ],
"h": 24,
"freq": "1h",
"model_options": {"nonnegative": true, "flip_average": false}
}model_options is a closed object: an unknown key returns 422 VALIDATION_ERROR. A key the selected model does not take returns 422 MODEL_OPTION_UNSUPPORTED (details.model, details.unsupported, details.supported); hora-1.0 takes both keys.
4. Other capabilities
- Missing values: the server always hands the model cleaned, filled values, so
model_input[].missing_modeisfilled; imputed points are not counted infed_pointsand are not billed. Two cases are reported separately inmodel_input[]: trailing empty values kept from policy version2026-12on are not used as data (masked_tail,tail_handling), and withoptions.cleaning.long_gap: "mask"the model reads long interior gaps as missing values rather than filled ones, reported aslong_gap_pointswithlong_gap_handling: "mask". - Quantiles:
hora-1.0natively produces 0.01, 0.05, 0.10, 0.15 … 0.90, 0.95, 0.99. The service never interpolates; for non-native quantiles see Prediction Intervals. - Covariates: the model does not use covariates today. The API still accepts covariate columns (at most 8 per entity) and reports them per column:
model_input[].covariates_usedisfalseand each column that passes the data checks is reportedmodel_unsupported. The per-column report inmodel_input[].covariatesis authoritative; see Covariate Support. - Temporarily unavailable: if the model is unavailable, the call returns 503
SERVICE_UNAVAILABLE(not billed; retry later). A busy model returns 503MODEL_BUSYwithRetry-After. - Other values: any
modelother thanhora-1.0orhorareturns 422MODEL_NOT_AVAILABLEbefore any quota is reserved;details.availablelists the accepted ids.
{
"error": {
"code": "MODEL_NOT_AVAILABLE",
"message": "Model 'my-model' is not available; use 'hora-1.0'",
"request_id": "req_…",
"details": {"model": "my-model", "available": ["hora", "hora-1.0"]}
}
}