Data specification¶
HTTP and the Python client share one predict contract. Only the transport changes: JSON embeds tables in the request, while the Python client converts them to Arrow.
Request fields¶
| field | required | description |
|---|---|---|
past |
yes | Historical observations as a table. It must contain the time column and every target column. |
fh |
yes | Number of steps ahead. Must be greater than zero. |
time |
no | Name of the time column. Defaults to the first column of past. |
target |
no | Target column name or list of names. See column inference. |
model |
no | Loaded model. Defaults to naive. |
future |
no | Future values of time-varying covariates. When present, it must contain the time column. |
static |
no | One row of values that remain constant over time. |
quantiles |
no | Quantile levels passed to models that support quantile forecasts. |
past is not a 1-d vector or a pandas index. It is a table with one row per timestamp:
Time must be a column. For a pandas object with time in its index, use reset_index() before sending it.
Table formats¶
Column-oriented dictionaries¶
Each key is a column name. Each value is a list, and all lists must have the same length:
JSON and Python both accept this shape.
Row-oriented dictionaries¶
Use columns plus a list of rows. Each row must have one value for every column:
{
"columns": ["timestamp", "sales"],
"data": [
["2024-01-01", 120],
["2024-01-02", 135],
["2024-01-03", 128]
]
}
The dictionary must contain only columns and data. JSON and Python both accept this shape.
Python tables¶
Client.predict(...) also accepts pandas, polars, pyarrow, and Narwhals tables:
These native frames are Python inputs. JSON POST /predict uses one of the two dictionary shapes above.
Column roles¶
Time¶
time names the time column. Omitted, it is the first column of past. When you send future, that column has to be there too.
Integer and datetime values are kept. Strings, including JSON dates, are parsed as datetimes.
Targets¶
target is one name or a list. A string becomes a one-element list. More than one target needs an estimator that supports multivariate forecasting. Which families do: Capabilities.
Column inference¶
You may omit time and target:
{
"past": {
"timestamp": ["2024-01-01", "2024-01-02", "2024-01-03"],
"sales": [120, 135, 128]
},
"fh": 3,
"model": "chronos_bolt"
}
TServe then uses:
- the first
pastcolumn astime; - every other
pastcolumn as a target, except columns also present infuture, which become exogenous features instead.
Specify target explicitly when a table contains columns that should not be forecast.
Prediction horizon and model¶
fh is a relative horizon. fh: 3 requests the next three steps after the last row in past.
model is a registry model loaded by the running process. It is not an executor name. If omitted, it defaults to naive. Use GET /models to see loaded models and the catalog to see available models.
Future and static data¶
static is one row of values that do not change. The sktime executor broadcasts that row across history and the forecast.
future is values you already know for the steps being forecast, such as a planned promotion. A non-target column is passed through only when it is in both past and future. A past-only column has no future values; a future-only column has no history. Estimators tagged capability:exogenous use the column; others ignore it.
fh stays relative: the forecast is the next fh steps after the last past row. future must hold a row for each of those steps. Extra rows are ignored. A future that skips the horizon is rejected. Omit future and the executor builds that index, so static alone needs no future table.
{
"past": {
"timestamp": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"],
"sales": [120, 135, 128, 142, 138],
"promo": [0, 1, 0, 0, 1]
},
"future": {
"timestamp": ["2024-01-06", "2024-01-07", "2024-01-08"],
"promo": [1, 0, 0]
},
"static": {"store_type": ["urban"]},
"time": "timestamp",
"target": ["sales"],
"fh": 3,
"model": "chronos_2"
}
Quantiles¶
Request quantile levels with a list:
The loaded estimator must support quantile prediction. timesfm_2_5 supports the levels above; Chronos Bolt and TTM do not. TServe forwards the values to the estimator, which may apply additional validation.
Point forecasts remain in predictions. Quantile forecasts are returned as a second table. Many estimators name those columns {target}_{level} (sales_0.1, sales_0.5, sales_0.9); timesfm_2_5 currently uses a positional prefix (0_0.1, 0_0.5, 0_0.9).
Response¶
Every successful prediction returns:
{
"predictions": {
"timestamp": ["2024-01-06T00:00:00"],
"sales": [139.96]
},
"quantiles": null,
"model": "chronos_bolt",
"request_id": "…"
}
predictionscontains the time column and point forecasts.quantilesis a second table when requested and supported; otherwise it isnullover JSON andNonein Python.modelis the model that served the request.request_ididentifies this call and is also included in predict error responses.
JSON responses always use column-oriented dictionaries. The Python client restores predictions and quantiles to the type used for past: a column dict, row dict, pandas DataFrame, polars DataFrame, pyarrow Table, or Narwhals DataFrame.
Validation and limits¶
TServe rejects requests when:
pastorfhis missing;fhis not greater than zero;- dictionary columns have different lengths;
- a row has a different width from
columns; pastdoes not contain the selected time and target columns;futureis present without the selected time column;- target inference leaves no target columns.
Panel and hierarchical inputs are not supported. Send one time series table per request. See Errors for HTTP statuses and Python exceptions.