Developer Docs: /v1/forecast and /v1/clean are live; create API Keys self-service on the SequenxAI Platform.

POST /v1/forecast

POST https://api.sequenxai.com/v1/forecast forecasts the history of one or more entities online. The server first cleans the data under the effective cleaning policy (the raw preset only checks its structure), then runs the selected model, and finally maps the forecast back onto timestamps. Authentication is described in Authentication & Headers.

1. Request examples

forecast.sh
export SEQUENX_API_KEY="sqx_live_..."   # created at https://platform.sequenxai.com

# 96 points at 15-minute steps, h=24, level=[80, 90], model hora-1.0
curl -sSO https://docs.sequenxai.com/data/power-grid-15m.json

curl -sS -X POST "https://api.sequenxai.com/v1/forecast" \
  -H "Authorization: Bearer $SEQUENX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Request-Id: quickstart-0001" \
  -d @power-grid-15m.json

2. Request body

FieldTypeRequiredDefaultNotes
modelstringNohora-1.0hora-1.0 or its alias hora; any other id returns 422 MODEL_NOT_AVAILABLE. Limits are in Models & Limits.
model_optionsobjectNo—Model switches nonnegative ("auto" / true / false, default "auto") and flip_average (default true). Closed object: an unknown key returns 422 VALIDATION_ERROR, a key the model does not take returns 422 MODEL_OPTION_UNSUPPORTED. Billing stays per forecast point. See Model options.
seriesarrayYes—Historical long-table rows, at least 1; together with future_covariates at most 200,000 rows per request (more returns POINTS_EXCEEDED). Each entity may not be longer than the model's maximum context (SERIES_TOO_LONG); send only the most recent points.
series[].unique_idstringYes—Entity identifier; one request may carry several entities.
series[].dsstringYes—Timestamp. An explicit offset (Z, +08:00) is honored; values without one are read in options.timezone, see Long Table, Frequency & Time Zones.
series[].ynumber or nullYes—Observation; null marks a missing value. The key itself must be present; non-finite numbers are rejected.
Other series[] columnsnumber / string / boolean / nullNo—Past covariates, at most 8 columns; aligned to the cleaned series and reported per column in model_input[].covariates. The model does not use covariates today; each column that passes the data checks is reported model_unsupported. See Covariate Support.
hintegerYes—Forecast horizon, 1–2048, and no larger than the model's maximum horizon, otherwise 422 HORIZON_EXCEEDS_MODEL.
freqstringNoInferredFrequency string, see Frequency strings. Inferred by the cleaning service when omitted; required with the raw preset.
levelinteger[]NoNoneInterval levels, each 1–99; duplicates are merged. Without it the response has no intervals. For quantiles a model cannot produce natively, see Prediction Intervals.
quantile_policynearest / strictNonearestBeta. nearest uses the nearest native quantile and labels the interval with the level actually delivered; strict returns 422 QUANTILE_UNSUPPORTED for any non-native quantile. Applies to point_quantile too.
point_quantilenumberNoNone (median)Beta. Quantile returned as y_hat (for example 0.7 for P70). 0.01–0.99 with at most 3 decimal places, otherwise 422 VALIDATION_ERROR. Mapped to the model's native quantiles under quantile_policy; see section 5 of Prediction Intervals.
clean_seriesbooleanNotruefalse detects without repairing: as soon as a repair is needed the call returns 422 TIMESTAMP_IRREGULAR or SERIES_DISCONTINUOUS.
clean_exogbooleanNotrueFill short covariate gaps linearly (up to the policy's short-gap limit); with false any gap makes the column unusable.
future_covariatesarrayNo—Future-known values, one row per unique_id and forecast stamp. Columns must also appear on series rows (422 COVARIATE_COLUMN_MISMATCH); y is not allowed (422 FUTURE_COVARIATES_INVALID).
options.timezonestringNoUTCIANA zone name (for example Asia/Shanghai) for reading ds values without an offset; unknown names return 422 VALIDATION_ERROR.
options.ds_formatdmy or mdyNo—Day/month order for D/M/YYYY-style stamps the data cannot prove on its own; otherwise AMBIGUOUS_DATE_FORMAT.
options.gap_split_min_stepsinteger ≥ 0NoAutomaticGap length in grid steps after which only the latest contiguous segment is kept; 0 disables the split.
options.cleaning.presetdefault / strict / rawNoSee belowCleaning preset. When omitted: key default, then organization default, then platform default (default).
options.cleaning.version2026-13 (2026-10 / 2026-11 / 2026-12 deprecated)No2026-13Rule-set version, resolved like the preset. We recommend omitting it; 2026-10, 2026-11 and 2026-12 will be removed after notice, and pinning one adds a cleaning_version_deprecated warning. See Policy versions.
options.cleaning.impute_method, seasonal_period, nonnegative, bounds, structural_zero, business_days, long_gapsee linkNo—Knobs of version 2026-11 and later (so also of the default 2026-13); under the deprecated 2026-10 they return 422 CLEANING_OPTION_UNSUPPORTED with details.requires_version. See the Cleaning Policy Reference.
options.cleaning.acceptstring[]No—Applies proposed decisions by id; at most 200 ids of up to 200 characters each.
options.cleaning.declinestring[]No—Reverts applied, reversible decisions by id; same limits.
options.router_strategyauto / ensemble / single / fastNo—Contract-reserved; the value is validated but has no effect today.

Fields outside the contract at the top level or inside options.cleaning return 422 VALIDATION_ERROR (details.errors[].field names the field, e.g. options.cleaning.imputer) and are never silently ignored; unknown keys directly under options are still ignored. Presets, accept and decline are explained in Cleaning Presets & Report.

3. Validation order

The server handles a request in this order; a failed check stops the request before later steps. No non-200 response is billed.

  1. Authentication and scope: 401 INVALID_API_KEY, 403 INSUFFICIENT_SCOPE. Then the account checks: 503 SERVICE_UNAVAILABLE with Retry-After while SequenxAI has paused the endpoint, 403 ACCOUNT_SUSPENDED, 403 ORG_PENDING_DELETION. Then Idempotency-Key, when sent: 400 VALIDATION_ERROR for a malformed key, 422 IDEMPOTENCY_KEY_REUSED, 409 IDEMPOTENCY_IN_PROGRESS; an identical retry of a finished request returns the stored result here, without counting toward the per-minute limit.
  2. Requests per minute per account (shared by all its keys): 429 with X-RateLimit-Policy: forecast-rpm. Rate-limited calls are not recorded.
  3. Body parsing and field validation: 400 MALFORMED_JSON, 422 VALIDATION_ERROR (including more than 8 covariate columns), FUTURE_COVARIATES_INVALID, COVARIATE_COLUMN_MISMATCH.
  4. Row cap (series plus future_covariates): 422 POINTS_EXCEEDED.
  5. Cleaning preset: 422 CLEANING_OPTION_UNSUPPORTED; raw without freq returns 422 VALIDATION_ERROR.
  6. Model: any id other than hora-1.0 / hora returns 422 MODEL_NOT_AVAILABLE, a model_options key the model does not take returns 422 MODEL_OPTION_UNSUPPORTED, temporarily unavailable returns 503 SERVICE_UNAVAILABLE; h above the model's limit returns 422 HORIZON_EXCEEDS_MODEL; with quantile_policy: strict, a non-native quantile (including point_quantile) returns 422 QUANTILE_UNSUPPORTED; an entity with more distinct timestamps (rows under raw) than the model's maximum context returns 422 SERIES_TOO_LONG.
  7. Daily point quota: reserves "rows + h × entities"; if that does not fit, 429 with X-RateLimit-Policy: forecast-daily-points.
  8. Cleaning (or the raw structural check): the 422 cleaning codes, RAW_INPUT_INVALID, SERIES_TOO_SHORT, and SERIES_TOO_LONG when the cleaned grid (filled slots included) is longer than the model's maximum context.
  9. Inference: 503 MODEL_BUSY, 504 GATEWAY_TIMEOUT, 503 SERVICE_UNAVAILABLE.
  10. Success: settles on the observed and forecast points the model actually handled and returns the rest of the reservation.

4. Response fields

FieldNotes
request_idServer request ID, same as the X-Request-Id header.
model_usedThe model ID that ran: hora-1.0, also when the request sent the alias hora.
freqYour freq as sent; when omitted, the inferred canonical token (for example h, 15min, MS).
point_quantileBeta. Present only when the request sent point_quantile: the native quantile actually served as y_hat (differs from the request when it was substituted).
forecast[]h rows per entity: unique_id, ds (UTC, YYYY-MM-DDTHH:MM:SSZ), y_hat, and intervals when level was requested. y_hat is the model's median (quantile 0.5) by default, not the expected value; with point_quantile it is that quantile.
forecast[].intervalsKeyed by the level string of the quantiles actually used ("80", "90"), each value {"lo", "hi"} with lo ≤ hi. See Prediction Intervals.
quantile_reportBeta. {policy, requested, used, substitutions[]}: the requested quantiles, the native quantiles actually used, and each substitution {requested, used}. With point_quantile it also has point_forecast: {requested, used, method}.
data_qualityLegacy quality summary: status (ok or cleaned), inferred_freq (set only when freq was omitted), missing_ratio (timestamp-gap share before repair), imputed_points, outlier_points_suppressed (always 0 today; outliers are flagged, never modified), timezone_normalized, notes.
usage.series_countEntities processed.
usage.input_data_pointsObserved points actually fed to the model, counted after the long-gap split, excluding imputed values and inserted stamps.
usage.forecast_data_pointsForecast points produced (h × entities).
usage.latency_msServer time from receiving the request to assembling the forecast; not an SLA.
effective_policy{id, preset, version, source}: the cleaning preset and version that applied, and its source (request / key / org / platform).
model_input[]Per entity: context_points (points handed to the model), fed_points (observed ones among them), truncated (always 0: a series longer than the model's context is rejected, never cut), missing_mode, covariates_used, and covariates[] (per column: name, role, used, reason) when covariates were sent. Present only when they apply: masked_tail and tail_handling (trailing empty values kept under policy version 2026-12), and long_gap_points, long_gap_handling and long_gap_reason (with options.cleaning.long_gap: "mask"; SequenxAI Omni reads long gaps as missing values, so long_gap_handling is "mask"; see Long gaps: fill or mask).
warnings[]Beta. Notices that did not stop the forecast; omitted when there are none. code is trailing_values_missing, long_gap_mask_unavailable or cleaning_version_deprecated, with unique_id when it concerns one entity. Codes may be added; read them before using the forecast.
cleaning_reportThe cleaning_report/1 structured report (Beta); absent with the raw preset. See Cleaning Presets & Report.

5. Response example

Numbers are illustrative and cleaning_report is abridged:

forecast-response.json
{
  "request_id": "req_4f1c8e2a9b7d4e0c8a3f5b6d7e8f9a0b",
  "model_used": "hora-1.0",
  "freq": "1h",
  "forecast": [
    {
      "unique_id": "meter-001",
      "ds": "2026-09-03T00:00:00Z",
      "y_hat": 140.6,
      "intervals": {
        "80": {"lo": 137.9, "hi": 143.2},
        "90": {"lo": 136.4, "hi": 144.8}
      }
    }
  ],
  "data_quality": {
    "status": "ok",
    "inferred_freq": null,
    "missing_ratio": 0.0,
    "imputed_points": 0,
    "outlier_points_suppressed": 0,
    "timezone_normalized": true,
    "notes": []
  },
  "usage": {
    "series_count": 1,
    "input_data_points": 48,
    "forecast_data_points": 24,
    "latency_ms": 812
  },
  "effective_policy": {
    "id": "default@2026-13",
    "preset": "default",
    "version": "2026-13",
    "source": "platform"
  },
  "model_input": [
    {
      "unique_id": "meter-001",
      "context_points": 48,
      "fed_points": 48,
      "truncated": 0,
      "missing_mode": "filled",
      "covariates_used": false
    }
  ],
  "quantile_report": {
    "policy": "nearest",
    "requested": [0.05, 0.1, 0.5, 0.9, 0.95],
    "used": [0.05, 0.1, 0.5, 0.9, 0.95],
    "substitutions": []
  },
  "cleaning_report": {
    "schema_version": "cleaning_report/1",
    "policy": {"id": "default@2026-13", "...": "..."},
    "overall": {"series_count": 1, "input_points": 48, "output_points": 48, "...": "..."},
    "series": ["..."],
    "warnings": [],
    "blocking": [],
    "decisions": []
  }
}

6. The raw preset

options.cleaning.preset: "raw" skips cleaning and only runs a structural check before the model. Use it for data you already clean in your own systems. Requirements:

  • freq is required and must be a fixed step (s, min, h, D, W and multiples); calendar frequencies such as MS or M@15 are not supported.
  • Every ds is exactly YYYY-MM-DDTHH:MM[:SS[.ffffff]] followed by Z or ±HH:MM; no other format is accepted.
  • Each entity's rows are strictly increasing in time, one freq step apart; nothing is sorted, de-duplicated or filled.
  • Every y is a finite number, never null.
  • It cannot be combined with accept / decline or cleaning parameters such as impute_method (422 CLEANING_OPTION_UNSUPPORTED).

Otherwise the call returns 422 RAW_INPUT_INVALID. details.violations lists up to 20 problems, each with unique_id, index and reason, where reason is one of freq_invalid, calendar_freq_unsupported, ds_format, ds_duplicate, ds_not_increasing, step_mismatch, not_observed:

raw-input-invalid.json
{
"error": {
  "code": "RAW_INPUT_INVALID",
  "message": "Raw input is not a regular, finite series",
  "request_id": "req_…",
  "details": {
    "violations": [
      {"unique_id": "meter-001", "index": 5, "reason": "step_mismatch"}
    ],
    "hint": "Use the default cleaning preset, or call /v1/clean to see the cleaning report."
  }
}
}

Raw responses carry no cleaning_report, and data_quality is always {"status": "ok", "missing_ratio": 0.0}. Under raw the row count of each entity is checked against the model's maximum context before anything runs (SERIES_TOO_LONG); nothing is cut.