Analysis
Correlation, relevance, and causality between signals.
Understand your data before you train anything: how signals move together (correlation), which ones matter (relevance), and which ones drive others (causality). If you'd rather skip straight to answers, a goal runs discovery for you.
The three read endpoints are cached against a fingerprint of your data —
they recompute only when the workspace's data actually changes. Every
response carries a cached flag, and ?refresh=true forces a recompute.
Correlation
The pairwise correlation matrix across your numeric signals:
curl "$API_BASE/v1/signal/correlation" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.signals.get_signal_correlation()
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.signals.getSignalCorrelation();
{
"data": {
"correlations": {
"correlation": {
"daily_sales": { "daily_sales": 1.0, "foot_traffic": 0.83, "web_traffic": 0.41 },
"foot_traffic": { "daily_sales": 0.83, "foot_traffic": 1.0, "web_traffic": 0.37 },
…
}
},
"cached": false
}
}Query parameters
| Parameter | Meaning |
|---|---|
granger optional | true includes Granger-causality results alongside the matrix (a lighter alternative to the full causality scan). |
refresh optional | true forces a recompute, bypassing the cache. |
An empty matrix is a legitimate outcome. When there's too little or degenerate data, the response includes a diagnosis instead of pretending the workspace is empty:
{
"data": {
"correlations": {
"correlation": {},
"insufficient": { "reason": "need_two_signals", "signals": 1 }
},
"cached": false
}
}Reasons: no_data, need_two_signals, no_time_spread, no_overlap,
insufficient_points.
Relevance
A normalized 0–1 score per key — how connected each signal is to the rest of the workspace. This is the same score the signal list's default sort uses:
curl "$API_BASE/v1/signal/relevance" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.signals.get_signal_relevance()
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.signals.getSignalRelevance();
{
"data": {
"relevance": {
"daily_sales": 0.94,
"foot_traffic": 0.81,
"web_traffic": 0.52
}
}
}An empty workspace returns {"data": {"relevance": []}}.
Causality
A windowed Granger-causality scan: which signals drive which, at what lag, with what strength, and how stable that relationship is over time. This is the most expensive read endpoint — results are cached until your data changes.
curl "$API_BASE/v1/signal/causality?windows=5&significance_level=0.05" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.signals.get_signal_causality(params={"windows": 5, "significance_level": 0.05})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.signals.getSignalCausality({ params: { windows: 5, significance_level: 0.05 } });
{
"data": {
"causality_results": {
"granger_results": {
"foot_traffic -> daily_sales": {
"cause": "foot_traffic",
"effect": "daily_sales",
"status": "success",
"optimal_lag": 1,
"min_p_value": 0.0123,
"is_significant": true,
"strength": 0.9877,
…
}
},
"causality_network": {
"nodes": ["foot_traffic", "daily_sales", "web_traffic"],
"edges": [ { "from": "foot_traffic", "to": "daily_sales", "strength": 0.9877, "optimal_lag": 1, … } ],
"network_stats": { "total_variables": 3, "significant_relationships": 2, "network_density": 0.33, … },
…
},
"significant_relationships": [ { "cause": "foot_traffic", "effect": "daily_sales", "relationship_type": "very_strong", … } ],
"lag_analysis": { … },
"window_stability": { … },
"correlation_matrix": { … },
"metadata": { "max_lag_tested": 5, "significance_level": 0.05, "windows_analyzed": 5, … }
},
"cached": false
}
}Query parameters
| Parameter | Meaning |
|---|---|
windows optional | Time windows for stability analysis, 1–20. Defaults to 5. |
signal_count optional | Data points per window, 10–1000. Defaults to 50. |
max_lag optional | Longest lag to test, 1–15. Auto-selected by default. |
significance_level optional | P-value threshold, 0–1. Defaults to 0.05. |
refresh optional | true forces a recompute, bypassing the cache. |
Reading results: strength is 0–1 (above 0.8 is very strong),
optimal_lag is how many periods the effect trails the cause, and
window_stability separates persistent relationships from transient
ones.
Out-of-range parameters return 400 (e.g.
"Number of windows must be between 1 and 20"). Insufficient data
returns 200 with an error field in the payload rather than failing.

