Activity & pricing
The goal's activity feed and audit timeline, what goals cost, and publishing the goal's segment.
The activity feed
One call answers "what's happening and what's next": the goal's lifecycle as four phases — Discover → Auto-fit → Deploy → Live — each with a state, plain-language reasoning, and a next-step action:
curl "$API_BASE/v1/goals/$GOAL_ID/activity" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.goals.get_goals_by_goal_id_activity(GOAL_ID)
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoalsByGoalIdActivity(GOAL_ID);
{
"data": {
"goal_id": "b7e9c2d4-…",
"status": "serving",
"phases": [
{
"id": "discover",
"title": "Discover drivers",
"state": "done",
"summary": "7 drivers found",
"reasoning": "3 more are suggestive (shown dimmed in the graph).",
"metrics": [{ "label": "Candidates", "value": 64 }, { "label": "Drivers", "value": 7 }],
"cta": { "label": "Re-run", "action": "rerun" },
"refs": { "run_id": "a1f3…" }
},
{
"id": "fit",
"title": "Auto-fit best model",
"state": "done",
"summary": "Best model · Driver-weighted trees",
"metrics": [{ "label": "Accuracy", "value": "91.4%" }, { "label": "Skill", "value": "34.2%" }],
"refs": { "tournament_id": "e7a1…", "model_id": "9f2c41d8-…", "training_id": "t_5b2e…" }
},
{ "id": "deploy", "title": "Deploy to serving", "state": "done", "summary": "Live", "refs": { "promotion_id": "p_88c1…" } },
{ "id": "live", "title": "Monitor & retrain", "state": "active", "summary": "Full autopilot" }
],
"stats": {
"drivers": { "validated": 7, "exploratory": 3 },
"model": { "label": "Driver-weighted trees", "score": 8.41, "accuracy": 91.4, "skill": 34.2, "state": "done" },
"deploy": { "state": "done", "live": true, "status": "deployed" },
"serving": { "inference_count": 212, "last_inference_at": "2026-07-15T06:00:12+00:00", "next_inference_at": "2026-07-16T06:00:00+00:00", "live": true }
},
"resources": {
"model_id": "9f2c41d8-…",
"training_id": "t_5b2e…",
"segment_id": "seg_44aa…",
"deployment_id": "p_88c1…",
"last_inference_id": "3f1a…"
},
"config": { "auto_fit": true, "auto_deploy": "review", "autopilot": "full", "retrain": "auto", "live": true }
}
}Phase states are pending, active, review (waiting on you), done,
failed, or off. resources gives you stable IDs into the underlying
artifacts — the champion model, its training, segment, deployment, and the
latest forecast. Poll this while work is in flight, or subscribe to the
goal's realtime channel instead.
The timeline
The autopilot's accountability record: every automated action with its trigger, references, and charge — plus the current autopilot status:
curl "$API_BASE/v1/goals/$GOAL_ID/timeline?limit=50" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.goals.get_goals_by_goal_id_timeline(GOAL_ID, params={"limit": 50})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoalsByGoalIdTimeline(GOAL_ID, { params: { limit: 50 } });
{
"data": {
"goal_id": "b7e9c2d4-…",
"autopilot": {
"mode": "full",
"monthly_spend_cap": 500.0,
"month_spend": 75.0
},
"timeline": [
{
"ts": "2026-07-14T02:10:00+00:00",
"actor": "system",
"action": "retrain_triggered",
"reason": "drift detected on ad_spend",
"refs": { "training_id": "t_77e0…" },
"charge": 50.0
},
{
"ts": "2026-07-10T09:12:00+00:00",
"actor": "user",
"action": "serve_requested",
"reason": "Forecast now",
"refs": {},
"charge": 0.0
}
]
}
}| Parameter | Meaning |
|---|---|
limit optional | Rows returned, newest first, capped at 200. |
month_spend sums the automated charges
this UTC month; when the next automated action would exceed
monthly_spend_cap, the autopilot pauses itself and notifies you —
monitoring continues, spending stops.
What goals cost
Goals charge per action, upfront, with automatic refunds when an action fails to start:
| Action | Charged when | Rate key |
|---|---|---|
| Discovery run | Queued — at creation and on every re-run | discovery.run (scaled 1×/2×/4× by workspace candidate volume) |
| Tournament | Queued | discovery.tournament (scaled by model selection) |
| Live day | Per day a goal serves | discovery.live_day |
| Prediction | Per inference on Shared serving | see Billing |
| Scenario / parse / explain / sensitivity | Per run; saved results are free to view | discovery.scenario* |
| Automated retrain | When the autopilot retrains | standard training meters |
| Fleet bake-off | Once at fleet goal creation | discovery.fleet_bakeoff |
| Fleet scoring run | Every fleet run, priced in member blocks | discovery.fleet_run |
| Fleet scenario | Per covariate-shock scenario | discovery.fleet_scenario |
The create response's credits_charged is the first run's charge;
GET /v1/goals/price
shows every rate for your plan before you commit, and
GET /v1/goals/{goal_id}
reports the goal's lifetime total_cost. Rates, credits, and the ledger
live in Billing.
Publish the goal's segment
Discovery compiles an internal segment — the target plus its validated drivers, correctly lagged. Publish it as a normal, editable segment you can use in your own pipelines:
curl -X POST "$API_BASE/v1/goals/$GOAL_ID/publish-segment" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.goals.post_goals_by_goal_id_publish_segment(GOAL_ID)
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.postGoalsByGoalIdPublishSegment(GOAL_ID);
{
"data": {
"segment": {
"uid": "seg_9b3d…",
"name": "Daily sales · discovered drivers",
"origin": "discovery_published",
"…": "…"
},
"created": true
}
}A 201 means a fresh copy was created. Publishing is idempotent: while the
published copy exists, calling again returns it with 200 and
created: false. The copy is yours — it counts toward your plan's segment
quota (403 — "Segment limit exceeded. Your plan allows 10 segments per workspace.") and editing it never affects the goal, which keeps serving
from its own internal segment.

