Predict.aiDocs
Goals

Discovery

What a discovery run does stage by stage, how to re-run one, and how to take manual control.

A discovery run is how a goal learns. The first one is queued at creation; after that you re-run whenever you want (or let the goal's discovery policy trigger runs for you).

What a run does

Every run walks the same funnel. Each stage narrows the candidate set and records what it kept, what it rejected, and why:

StageWhat happens
profileMeasure the target: cadence, gaps, seasonality — and resolve every auto setting from data
representBuild the aligned data grid all later stages read
generateGenerate candidate features from the workspace's signals and events, adapted to the profile
screenFast statistical screen — drop candidates with no detectable relationship
pruneDeduplicate near-identical survivors
characterizeMeasure each survivor: direction, best lag, response shape
segment_compileCompile the goal's internal segment from the survivors
liftTest real predictive lift on walk-forward folds
fdr_stabilityValidate: false-discovery control plus stability across folds
consolidateWrite the validated relationships as graph edges
expandSearch for multi-hop pathways behind the direct drivers

The output is the goal's relationship graph. When auto-fit is on (the default), a completed run flows straight into a tournament.

Re-run discovery

curl -X POST "$API_BASE/v1/goals/$GOAL_ID/run" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "run_id": "c4d8…",
    "status": "queued",
    "credits_charged": 25
  }
}

The 202 means a new run is queued. Existing relationships aren't thrown away — the funnel re-validates them against fresh data and archives only the ones that no longer hold.

StatusWhyExample message
402Not enough creditserror.code insufficient_credits
404Goal doesn't exist in this workspace"Goal not found"
409One run at a time per goal"A run is already in progress for this goal"

Inspect a run

curl "$API_BASE/v1/goals/runs/$RUN_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "run": {
      "run_id": "c4d8…",
      "goal_id": "b7e9c2d4-…",
      "origin": "user",
      "status": "running",
      "config_snapshot": {
        "target_key": "daily_sales",
        "goal_type": "forecast_value",
        "horizon_bins": 14,
        "interval_seconds": 86400,
        "stage_order": ["profile", "represent", "generate", "…"]
      },
      "data_snapshot": { "n_candidates": 64 },
      "stages": {
        "profile":  { "status": "completed", "in_count": 1,  "out_count": 1,  "rejected": {} },
        "screen":   { "status": "completed", "in_count": 64, "out_count": 21, "rejected": { "no_relationship": 43 } },
        "lift":     { "status": "running",   "in_count": 12, "out_count": null, "rejected": {} },
        "…": {}
      },
      "error": null,
      "created_at": "2026-07-15T09:12:04+00:00",
      "started_at": "2026-07-15T09:12:09+00:00",
      "finished_at": null
    }
  }
}

status is queued, running, completed, or failed (with error set). Each stage reports in_count/out_count and per-reason rejected counts — the funnel, in numbers. The config_snapshot pins the settings the run actually used, so old runs stay interpretable after you retune the goal.

Poll this while a run is in flight, or subscribe to the goal's realtime channel for goal.run.* events instead.

The timeline

Every run — manual, scheduled, or automated — lands in the goal's timeline with its trigger and charge:

curl "$API_BASE/v1/goals/$GOAL_ID/timeline" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"

See Activity & pricing for the response shape.

Manual control: train and serve

Automation is the default, but both halves of the loop have a manual lever.

Start a tournament yourself — useful when auto-fit is off, or after a re-run when you want fitting on your schedule:

curl -X POST "$API_BASE/v1/goals/$GOAL_ID/train" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "tournament_id": "e7a1…",
    "status": "queued",
    "credits_charged": 40
  }
}

Returns 409 ("A tournament is already in progress for this goal") if one is running, 402 if credits are short. The full tournament flow is on Tournament & champion.

Produce one forecast now with the current champion — the manual serving action, also handy as a "refresh forecast" button:

curl -X POST "$API_BASE/v1/goals/$GOAL_ID/serve" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{ "data": { "goal_id": "b7e9c2d4-…", "status": "queued" } }

Returns 409 ("No deployed champion to forecast with") until a champion is live. The serve is idempotent per data window — if nothing new has arrived, the platform doesn't charge you to reproduce the same forecast.

On this page