PowerForecast Docs
Back to Wizard
This page belongs to the full documentation. You don't need it to plan: back to the essentials.

API Reference

The forecast engine is a FastAPI service (forecast-api/, port 8020). Base path: /api/powerforecast/v1. OpenAPI: /docs and /openapi.json.

Endpoints

MethodPathDoes
POST/jobssubmit a forecast; answers at once with the job id (status: partial)
GET/jobs/{jobId}job status: partial while PENDING / RUNNING, success when DONE, failed with the error
GET/jobs/{jobId}/resultthe forecast result (below) once DONE
GET/jobs/{jobId}/diagnosticsthe residual diagnostics once DONE
POST/forecastsame pipeline, synchronous: the result in one call (long for many series)
GET/runsthe stored forecasts (below)
GET · PATCH · DELETE/runs/{id}one stored forecast: read (with spec, result, diagnostics), rename, delete
POST/runs/{id}/restore, /runs/{id}/copy-specundo a delete; the stored request, to start a new forecast from it
GET/runs/{id}/auditits history
POST/runs/importstore the files of an earlier run: {name?, spec?, result, diagnostics?} → 201 (history action import)
GET/modelsthe methods the engine knows
GET/enterprise-infowhat the profiling and validation stages do
GET/health, /info(no prefix) liveness and service information

The wizard uses the asynchronous flow: POST /jobs, poll GET /jobs/{id} every 0.5 s, then /result and /diagnostics.

Stored forecasts (/runs)

Every job the engine runs (/jobs or /forecast) is also stored as a run in the product's SQLite database (/data/powerforecast.db, volume powerforecast-data): the full request (input series included), the result, the diagnostics, the status (RUNNING, DONE, FAILED), who asked (header X-PPT-User, else caller, else api) and when. Runs never expire. Redis still holds the jobs while they run and for RUN_TTL_SECONDS after; once a job left Redis, GET /jobs/{id}, /result and /diagnostics answer from the stored run, so a finished job never vanishes. GET /jobs/{id} also gives run_id.

A request with call_context: "critic" (the AI Forecast Critic's trials) is stored with kind: "trial" and left out of GET /runs unless kind=trial or kind=all.

Query of GET /runsMeaning
querytext in the name or description (any case, accents included)
kindrun (default), trial or all
statusRUNNING, DONE or FAILED
include_deletedalso the deleted runs
limit, afterpage size (≤ 500) and the id of the last row of the previous page (payload.next)

Delete is two-step: DELETE /runs/{id} hides the run (restorable with POST /runs/{id}/restore); DELETE /runs/{id}?purge=true on a deleted run removes it for good (the history keeps its name and hash). Errors: NOT_FOUND 404, NOT_DELETED 409 (purge or restore of a run that is not deleted), TOO_LARGE 413 (a request over FORECAST_MAX_JSON_MB, 50 MB, refused by /jobs and /forecast before any work).

No sign-in check yet. Anyone who can reach the API can list, change and remove stored forecasts. Accepted until the product has its own authentication; keep backups (installation guide).

The envelope

Every response of /api/powerforecast/v1 is a PDP ProductResponseEnvelope:

{
  "jobId": "jobId_1792874861471",
  "producer": "PowerForecast",
  "status": "success | partial | failed",
  "timestamp": "2026-10-25T09:12:03.120Z",
  "execution_time_ms": 48160,
  "payload": { },
  "errors": [ { "code": "VALIDATION_ERROR", "message": "…", "recoverable": true } ],
  "trace": { "caller": "self", "call_context": "standalone" }
}

A refused or failed forecast still answers HTTP 200 with status: failed and errors[].

CodeWhen
VALIDATION_ERRORthe request does not fit (e.g. a series with no value)
PIPELINE_PRODUCED_EMPTY_RESULTSthe pipeline ran but produced no usable forecast
PIPELINE_ERRORan unexpected engine error
NOT_FOUND, JOB_FAILED, RESULT_MISSING, DIAGNOSTICS_MISSINGjob lookups

Request (POST /jobs, POST /forecast)

{
  "caller": "self", "call_context": "standalone",
  "name": "US retail sales 2026 budget",
  "description": "…",
  "business_target": "revenue",
  "granularity": "per_category",
  "scenario_type": "baseline",
  "frequency": "M",
  "horizon": 12,
  "confidence_level": 0.95,
  "models": null,
  "handle_missing": true,
  "handle_outliers": true,
  "data": [
    { "unique_id": "Grocery stores", "ds": ["2015-01-01", "2015-02-01", "…"], "y": [48210.0, 45102.0, "…"] }
  ]
}
FieldValues
frequencyH, D, W, M, Q, Y
horizon1 – 365 periods
confidence_level0.5 – 0.99 (the wizard offers 0.8, 0.9, 0.95, 0.99)
modelsnull or ["Auto"] = automatic; or a list among AutoARIMA, ETS, SeasonalNaive, Naive, Theta, MSTL
enterprise_mode, validate_patternsdefault true: consensus profiling and holdout validation of patterns
name, description, business_target, granularity, scenario_typelabels kept with the run
caller, call_contexttrace (self / standalone for the wizard; PowerOrchestrator sets its own)

Result (payload of /jobs/{id}/result)

FieldHolds
jobId, status (completed), business_target, frequency, horizon, series_count, execution_time_ms, models_usedthe run
forecasts[]per series: unique_id, model_used, forecasts[] (ds, yhat, yhat_lower, yhat_upper), interval_method (model or none), accuracy
forecasts[].accuracycross-validation: method, champion, mape, rmse, mae, baseline_model (Naive), baseline_rmse, candidates (each method's mape, rmse, mae)
profiling[], enterprise_profiling[]per series: count, mean, std, trend / seasonality / variance detection with consensus and validation, recommended transform and outlier method, data_quality, profile_reliability, warnings
validation_summarycounts over all series
diagnostics, enterprise_diagnosticsoverall_quality, quality_score, recommendations, test_summary
decisions[]the engine's decision log: category (profiling, transform, outlier, model), series_id, decision, rationale, confidence, alternatives, metrics

The wizard adds data (the input series) to the saved results file, so the Results page can draw the history.

Diagnostics (payload of /jobs/{id}/diagnostics)

residual_diagnostics[] per series: residual_mean, residual_std, skewness, kurtosis, has_bias (with its p-value), is_normal (normality tests), is_uncorrelated (Ljung-Box, Durbin-Watson), is_homoscedastic (Breusch-Pagan and others), analysis_scale, failed_tests. Plus overall_quality, quality_score, recommendations, test_summary.

Example

curl -s -X POST http://localhost:8020/api/powerforecast/v1/jobs \
     -H "Content-Type: application/json" --data-binary @forecast-demos/04-us-retail-sales-budget/spec.budget.json
# -> { "status": "partial", "jobId": "jobId_…" }
curl -s http://localhost:8020/api/powerforecast/v1/jobs/jobId_…            # until "status": "success"
curl -s http://localhost:8020/api/powerforecast/v1/jobs/jobId_…/result

Jobs, results and diagnostics are kept in Redis with a time-to-live; when a job has expired, the engine can ask PowerOrchestrator for it.