Create & manage
Create, list, inspect, edit, and delete goals — plus the free previews to use before you pay.
Create a goal
target_key and goal_type are required. Everything else is optional and
resolved automatically from your data (see
auto-everything). To target a
whole population of signals instead of one, pass goal_kind: "fleet"
with a target_selector — see Fleet goals.
curl -X POST "$API_BASE/v1/goals" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"target_key": "daily_sales",
"goal_type": "forecast_value"
}'from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.goals.post_goals(json={
"target_key": "daily_sales",
"goal_type": "forecast_value",
})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.postGoals({
json: {
target_key: "daily_sales",
goal_type: "forecast_value",
},
});
{
"data": {
"goal_id": "b7e9c2d4-…",
"run_id": "a1f3…",
"status": "queued",
"credits_charged": 25
}
}A 201 means the goal exists and its first discovery run is queued —
credits_charged is the upfront run charge. Watch progress with
GET /v1/goals/runs/{run_id} or
subscribe to the goal's realtime channel.
Request body
| Field | Meaning |
|---|---|
target_key required | The signal to predict. Fleet goals send a target_selector instead. |
goal_type required | forecast_value, forecast_distribution, trend, or anomaly — or rank_by_risk / rank_by_growth with goal_kind: "fleet" (Fleet goals). |
name optional | Display name. Auto-generated from the target when omitted. |
horizon_bins optional | Forecast steps, 1–500. Auto-resolved from your data's cadence when omitted. |
interval_seconds optional | Data resolution, ≥ 60. Auto-resolved when omitted. |
scope optional | {"type": "workspace"} (default) or {"type": "segment", "segment_id": "…"}. |
options optional | Automation knobs — fields below. |
The options object:
| Field | Meaning |
|---|---|
autopilot optional | full (act automatically), review (propose, you approve), or paused. |
discovery_policy / retrain_policy / serving_policy optional | Each auto, scheduled, or manual. |
pipeline optional | { "auto_fit": true, "auto_deploy": "off" | "review" | "auto" }. |
model_selection optional | Include/exclude lists for the tournament lineup. |
monthly_spend_cap optional | Credit ceiling for the goal's automated spending. |
Errors
| Status | Why | Example message |
|---|---|---|
400 | Missing or invalid field | "target_key is required" · "goal_type must be one of forecast_value, forecast_distribution, trend, anomaly" · "horizon_bins must be between 1 and 500" |
402 | Not enough credits for the first run | error.code insufficient_credits — the goal is not created |
403 | Plan quota reached | "Discovery goal limit reached. Your plan allows 3 goals per workspace." |
List goals
curl "$API_BASE/v1/goals" \
-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()
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoals();
{
"data": {
"goals": [
{
"goal_id": "b7e9c2d4-…",
"name": "daily_sales · forecast value",
"target_key": "daily_sales",
"goal_type": "forecast_value",
"horizon_bins": 14,
"interval_seconds": 86400,
"status": "serving",
"shock_state": "normal",
"champion_pipeline_id": "9f2c41d8-…",
"edges_count": 7,
"last_run": {
"run_id": "a1f3…",
"status": "completed",
"created_at": "2026-07-15T08:30:00+00:00",
"finished_at": "2026-07-15T08:41:12+00:00",
"error": null
},
"created_at": "2026-07-15T08:30:00+00:00"
}
]
}
}Each row carries the goal document plus two computed fields: edges_count
(active relationships in the graph) and last_run
(a slim summary of the most recent discovery run).
Fleet goals appear in the same list with
goal_kind: "fleet", their target_selector, and a fleet sub-document
(chosen model, member_count, last run stats). The hidden companion goal a
fleet maintains for driver discovery is not listed.
Inspect one goal
curl "$API_BASE/v1/goals/$GOAL_ID" \
-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(GOAL_ID)
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoalsByGoalId(GOAL_ID);
{
"data": {
"goal": { "goal_id": "b7e9c2d4-…", "target_key": "daily_sales", "…": "…" },
"latest_run": { "run_id": "a1f3…", "status": "completed", "stages": { "…": "…" } },
"total_cost": 112.5
}
}total_cost is the goal's net lifetime spend in credits — every charge
(runs, tournaments, scenarios, automated retrains) minus refunds. Unknown
IDs return 404 with "Goal not found".
Edit a goal
Send only the fields you're changing:
curl -X PATCH "$API_BASE/v1/goals/$GOAL_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{ "name": "Daily sales", "autopilot": "review" }'from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.goals.patch_goals_by_goal_id(GOAL_ID, json={"name": "Daily sales", "autopilot": "review"})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.patchGoalsByGoalId(GOAL_ID, { json: { name: "Daily sales", autopilot: "review" } });
{ "data": { "goal_id": "b7e9c2d4-…", "updated": ["name", "options"] } }Request body
All fields optional — send only what changes.
| Field | Meaning |
|---|---|
name optional | Rename the goal. |
live optional | Streaming (true) vs historical (false) data. |
autopilot optional | full, review, or paused. |
discovery_policy / retrain_policy / serving_policy optional | Each auto, scheduled, or manual. |
monthly_spend_cap optional | Credit ceiling for automated spending. |
unit_economics optional | {"value_per_unit": 70, "currency": "$", "label": "per MWh"} — lets scenario results translate forecast deltas into money. null clears it. |
pipeline / model_selection optional | Same shapes as create. |
interval_seconds / horizon_bins / max_lag_bins optional | The tuning trio — see the callout below. |
Setting an explicit interval_seconds, horizon_bins, or max_lag_bins
also clears its auto flag — the profile stage stops re-resolving it on
later runs. Tuning changes reshape the next discovery run, not the
live champion.
| Status | Why | Example message |
|---|---|---|
400 | Invalid value, or empty patch | "autopilot must be full|review|paused" · "Nothing to update" |
404 | Goal doesn't exist in this workspace | "Goal not found" |
Delete a goal
curl -X DELETE "$API_BASE/v1/goals/$GOAL_ID" \
-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.delete_goals_by_goal_id(GOAL_ID)
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.deleteGoalsByGoalId(GOAL_ID);
{ "data": { "goal_id": "b7e9c2d4-…", "deleted": true } }Deletion is soft: the goal disappears from listings and its graph edges and
paths are archived. A segment you
published
from the goal is yours and survives. Deleting a
fleet goal also cascades: its hidden companion
goal, the fleet:* aggregate signals, and its stored scores and outcome
rows are cleaned up.
Preview the profile
Before creating anything, see what the platform detects about a target — cadence, liveness, history depth, seasonality — and what the auto settings would resolve to. Free and synchronous:
curl "$API_BASE/v1/goals/profile-preview?target_key=daily_sales&goal_type=forecast_value" \
-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_profile_preview(params={
"target_key": "daily_sales",
"goal_type": "forecast_value",
})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoalsProfilePreview({
params: {
target_key: "daily_sales",
goal_type: "forecast_value",
},
});
{
"data": {
"profile": {
"summary": "Daily series, 412 points over 14 months, strong weekly cycle.",
"traits": ["seasonal", "trending"],
"cadence": { "interval_seconds": 86400, "regular": true },
"liveness": { "live": true, "last_point_age_s": 61234 },
"history": { "n_points": 412, "span_days": 424 },
"seasonality": { "cycles": [{ "period_s": 604800, "strength": 0.72 }] },
"shapes": { "…": "…" },
"profile_version": 3
},
"resolved": {
"horizon_bins": 14,
"interval_seconds": 86400,
"max_lag_bins": 28
}
}
}| Parameter | Meaning |
|---|---|
target_key required | The signal to profile. |
goal_type optional | Shapes the resolved settings for a specific goal type. |
A target with too little history returns 422 with
error.code not_analyzable — the message
explains what's missing.
Price a goal before creating
curl "$API_BASE/v1/goals/price" \
-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_price()
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoalsPrice();
{
"data": {
"run_cost": 25,
"run_bucket": 1.0,
"candidates_estimate": 64,
"tournament_cost": 40,
"live_day_cost": 2,
"inference_cost": 0.1,
"hosting_day_cost": 48,
"retrain_cost": 50.0,
"default_monthly_cap": 500.0,
"rediscovery_per_month": 1,
"balance": 1240,
"goals_limit": 3,
"goals_used": 1
}
}Run cost is bucketed by candidate volume (run_bucket is 1×, 2×, or 4× the
base rate). inference_cost is the per-prediction rate on Shared serving;
hosting_day_cost is the flat daily fee for a Private reservation instead.
Rates and the credit model live in Billing.
Find similar signals & events
The same learned-shape space that powers discovery recall is available directly — useful for choosing a target or exploring the workspace:
curl "$API_BASE/v1/goals/similar?kind=signal&key=daily_sales&k=5" \
-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_similar(params={"kind": "signal", "key": "daily_sales", "k": 5})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.goals.getGoalsSimilar({ params: { kind: "signal", key: "daily_sales", k: 5 } });
{
"data": {
"kind": "signal",
"results": [
{ "key": "store_visits", "similarity": 0.9312 },
{ "key": "web_orders", "similarity": 0.8877 }
],
"embedding_version": 2
}
}| Parameter | Meaning |
|---|---|
kind required | signal or event. |
key required | For kind=signal: the signal to find neighbors of. |
event_id optional | For kind=event: the event to find neighbors of (results carry event_id, stream, name, occurred_at, similarity). |
k optional | How many results, capped at 50. |
| Status | Why | Example message |
|---|---|---|
400 | Missing selector | "key is required for kind=signal" · "kind must be 'signal' or 'event'" |
503 | The similarity index is temporarily down | error.code similarity_unavailable (message: "The similarity index is not reachable right now."}}` |

