Appearance
KPI Equity Impact API
The KPI Equity Impact API tracks the company KPIs that move stocks — subscribers, deliveries, daily actives, cardholders, order volumes — before and after companies report them. For every upcoming print it puts three numbers side by side: what prediction markets currently expect (a live, real-money forecast with daily history and an uncertainty band), what Octagon's model estimates, and — once the company reports — the actual, with the beat/miss surprise scored automatically. One call returns a ranked board of upcoming and settled prints; a second returns the full event bundle for a single KPI, chart-ready. Liquidity is expressed as a tier (high / medium / low) instead of raw volume.
Like the Chat Completions and Responses endpoints, these are direct REST endpoints called relative to the Octagon API base URL:
text
https://api.octagonai.co/v1Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /predictions/kpi-events | The board — list / rank / search / paginate KPI events |
GET | /predictions/kpi-events/{event_id} | One KPI event — the full event bundle |
Conventions
KpiValue— every KPI-unit quantity is an object of the form{ "value": <number>, "unit": <string>, "formatted": <string> }(e.g.,{ "value": 28060000, "unit": "customers", "formatted": "28.06M" }). It isnullwhen the underlying number is absent.event_id— the primary key, owned by Octagon (e.g.,hood_funded_customers_2026q2). Curated series get a readable id; uncurated events get an opaqueevt_<hash>(andkpi_<hash>) — never an upstream ticker in any form.period— the fiscal period the market forecasts, parsed from the event text ("in Q2 2026"→Q2 2026;"in 2026"→FY 2026).code/label/kind/start/endare populated for ~97% of events;nullonly for genuine non-period markets (e.g., a one-off corporate announcement). Quarterstart/endare calendar quarters — a display window, not a fiscal-calendar mapping.- Probabilities are percentage points on a 0–100 scale (
model_probability: 90.0means 90%). newsworthiness— a0–100desk sort key composed additively of edge magnitude (up to 45), liquidity tier (up to 25), and report-date proximity (up to 30).- Actual trust gate — a captured actual that fails validation against market-derived bounds is withheld: the event stays
settledwithout anactualand never becomesreported. Categorical markets (outcomes are names, not numeric thresholds) never emit a numeric actual. - Units — curated series carry curated units; uncurated series infer a unit from the event text (e.g., "card members" →
members).unitmay be empty or absent only when genuinely unknown. - Errors — JSON
{ "detail": "…" };400bad parameters,401authentication,404unknown event,422validation.
Authentication uses the standard bearer token — see Authentication. Requests without a valid key return 401 {"detail": "Missing or invalid credentials"}.
List KPI events
GET /predictions/kpi-events
The board / reporting calendar.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | all (default) | active | settled | reported. |
sort | string | No | newsworthiness (default) | volume | edge | abs_edge | edge_pp | report_date | reported_at | close_time. |
q | string | No | Substring search over company / KPI name. |
period | string | No | Filter by period code (e.g. 2026q2; see Conventions). A comma-separated list matches any of the codes. |
limit | integer | No | Number of records to return. Default 50; minimum 1; maximum 200. |
cursor | string | No | Opaque pagination cursor. Use the next_cursor returned from a previous response to continue. |
The desk default is newsworthiness (highest first). report_date sorts by the reporting calendar (soonest expected report first); all other sorts are descending.
status semantics: settled means the event is past close, matching each row's status field — the actual may still be pending. reported means settled and a trusted actual is served (a captured-but-flagged actual — see the trust gate — does not count). "Settled but awaiting actual" is ?status=settled minus ?status=reported.
Response
jsonc
{
"as_of": "2026-07-07T00:00:00Z", // when this board snapshot was generated
"aggregates": { "total_events": 146, "total_markets": 1039, "total_volume": 4874975.01 }, // illustrative — the board grows
"sort": "newsworthiness",
"status": "all",
"data": [ /* rows, see below */ ],
"next_cursor": null,
"has_more": false
}aggregates.total_volume is the summed contract volume across the filtered set; it is not exposed on individual rows.
Row fields (data[])
| Field | Type | Description |
|---|---|---|
id | string | Octagon event_id (primary key). |
kpi_id | string | Stable across periods. |
company_name, company_ticker | string | null | company_ticker is the stock symbol; null for uncurated events. |
kpi_name | string | null | Human-readable KPI name. |
period, period_label, period_kind | string | null | Machine + human period + kind (best-effort; see Coverage). |
status | string | active | settled. |
expected_report_date | string | null | Expected report date. |
market_implied | KpiValue | Market-implied central from the latest stored snapshot — may lag the detail response's live central by up to a day; see market_implied_as_of. |
market_implied_as_of | string | null | Capture time of the row's stored snapshot. |
octagon_estimate_value | KpiValue | Octagon model central estimate. |
edge_absolute_value | KpiValue | Model minus market, in KPI units. |
actual | KpiValue | null | Settled reported figure. |
company_guidance | KpiValue | null | Company-issued guidance for the KPI, when available. |
model_probability, market_probability, edge_pp | number | null | Probability-space signal (percentage points). |
signal | string | null | above_market | in_line | below_market. |
near_settled | boolean | true when the market probability is ≥97% or ≤3% — the edge is settlement noise. |
newsworthiness | integer | 0–100 desk sort key. |
liquidity_tier | string | null | high | medium | low — replaces raw volume. |
strike_count, strike_period | integer / string | Market structure summary (no ladder detail). strike_count is a count; strike_period is an upstream-formatted period string (e.g. "26Q2") — prefer period / period_label. |
actual_source | string | null | Present only when a trusted actual is served. A neutral method label (never a provider name). |
reported_at | string | null | When the print's exact timestamp is known (market settlement/report time), that; otherwise a clearly-approximate fallback — the expected report date, then close time. Treat as "when the result landed, best available precision"; it can populate on settled rows even without a trusted actual. |
close_time | string | null | When the underlying markets close. |
Get one KPI event
GET /predictions/kpi-events/{event_id}
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
include_history | boolean | No | Include the prediction_market_estimate.trend series. Default true. |
selected_estimate_id | string | No | Pick a specific Octagon estimate run. |
start_ts, end_ts, period_interval | — | No | Forecast window (day-aligned UTC for period_interval=1440). |
percentiles | string | No | Accepted for compatibility; the public trend is the p50 series. |
The market central is a single basis — the median. The model central is the same statistic on the model side — the median (p50) of Octagon's model ladder — so edge_vs_market compares like with like and its direction always agrees with probability_signal.edge_pp.
Response
jsonc
{
"event_id": "hood_funded_customers_2026q2",
"kpi_id": "hood_funded_customers",
"company": {
"name": "Robinhood Markets, Inc.",
"ticker": "HOOD", // stock symbol, NOT an upstream market id
"exchange": "NASDAQ",
"sector": "Financials",
"industry": "Capital Markets"
},
"kpi": {
"title": "Funded Customers",
"description": "Funded Customers for Robinhood Markets, Inc.",
"unit": "customers",
"type": "accounts", // subscribers|deliveries|dau|mau|orders|accounts|revenue|margin|units|members|passengers|transactions|headcount|other
"directionality": "higher_is_better"
},
"period": { // best-effort; null when non-standard
"label": "Q2 2026", "code": "2026q2", "kind": "fiscal_quarter",
"start": "2026-04-01", "end": "2026-06-30"
},
"prediction_market_estimate": { // source-agnostic; no ticker/book/raw volume
"central": { "value": 28060000, "unit": "customers", "formatted": "28.06M" },
"as_of": "2026-07-06T00:00:00Z", // latest trend point
"trend": [ { "as_of": "2026-06-15T00:00:00Z", "value": 27500000 } ], // p50 over time
"liquidity_tier": "high",
"source": "aggregated_prediction_markets"
},
"octagon_model_estimate": {
"central": { "value": 28700000, "unit": "customers", "formatted": "28.7M" },
"confidence": 82,
"as_of": "2026-06-30T20:00:00Z",
"trend": [ { "as_of": "2026-06-28T00:00:00Z", "value": 28650000 } ],
"methodology_url": "https://octagonai.co/methodology/kpi"
},
"actual": { // null until a TRUSTED actual exists (see lifecycle)
"value": { "value": 28100000, "unit": "customers", "formatted": "28.1M" },
"reported_at": "2026-08-28T20:00:00Z", // exact when known (settlement/report time); else approximate (expected report date → close time)
"precision": "exact", // exact|rounded|range
"range": null, // market-derived cross-check band when available
"verified": true, // true only for company_report
"sources": [ { "name": "Company report", "url": "https://investors.robinhood.com/" } ],
"source_method": "company_report" // octagon_deep_research|company_report|market_ladder_reconstruction|market_settlement_value
},
"analysis": {
"edge_vs_market": {
"value": -640000, "unit": "customers", "formatted": "-640K",
"percent": -0.0223, "direction": "negative",
"signal": "below_market", // above_market|in_line|below_market
"model_as_of": "2026-06-30T20:00:00Z", // the compared values can be ~a day apart —
"market_as_of": "2026-07-06T00:00:00Z" // place the model dot by ITS as_of, never after a newer market point
},
"edge_vs_consensus": null,
"surprise": null, // populated once settled and reported
"model_accuracy": null,
"near_settled": false, // true when the market prob is ≥97% or ≤3%
"probability_signal": { // time-attributed: each side carries its own as_of
"model_probability": 62.0,
"market_probability": 58.0,
"edge_pp": 4.0, // = model_probability − market_probability
"badge": "leads", // leads (model above market) | rich (market above model) | confirms (aligned)
"model_as_of": "2026-06-30T20:00:00Z",
"market_as_of": "2026-07-06T00:00:00Z"
},
"newsworthiness": 74
},
"editorial": {
"status": "scheduled", // scheduled|imminent|reported|settled (reported = trusted actual served)
"expected_report_date": "2026-08-28",
"date_confirmed": false,
"change_since_last": null,
"headline": "Market sees Robinhood Markets, Inc. Q2 2026 Funded Customers near 28.06M; Octagon models higher at 28.7M",
"summary": "Prediction markets imply ~28.06M for Robinhood Markets, Inc.'s Q2 2026 Funded Customers, while Octagon's model points to 28.7M.",
"chart_url": null,
"octagon_report_link": "https://octagonai.co/reports/hood_funded_customers_2026q2",
"permalink": "https://octagonai.co/company-kpi-tracker/hood-funded-customers-2026q2",
"tags": [],
"peers": []
},
"as_of": "2026-07-07T00:00:00Z"
}Settled events & actuals — the lifecycle
What happens when a KPI event's period closes, and what consumers should expect:
active→settledon close. The event immediately appears under?status=settled;actualis stillnull(awaiting the print).- Actual capture (usually within a day — the settlement pipeline runs daily). The
source_methodon the actual tells you how it was obtained:market_settlement_value— the settlement venue published a clean numeric settlement figure that agrees with the market-derived range. Served asprecision: exact(orroundedfor abbreviated figures like148.5M), with the cross-checkrangeattached. Roughly two-thirds of actuals land this way.octagon_deep_research— no usable settlement figure, so the reported number is researched from primary sources (filings, shareholder letters) with citations insources, cross-checked against the market range when one exists.company_report— a directly-verified company figure (verified: true); reconciles or overwrites earlier methods when available.
settled→reportedthe moment a trusted actual is served;surprise(actual vs. the pre-report market median) populates on the detail response.
The trust gate: every researched actual is validated against market-derived bounds. A value that fails validation is never served — the event stays settled without an actual rather than showing a suspect number. Categorical markets (outcomes are names, not numeric thresholds — e.g., "which company ships the top model") never emit a numeric actual; they remain settled permanently.
Coverage & known gaps
The board tracks every KPI-tagged prediction market event (146 and growing as of July 2026):
- Uncurated events return
company_ticker: nulland a derivedcompany_name; theirevent_id/kpi_idare opaqueevt_<hash>/kpi_<hash>. Units are inferred from the event text (e.g.,members,vehicles,USD). Market/model estimates, edge, and signal populate from the market data regardless of curation. periodis parsed from the event text (see Conventions) and is clean for ~97% of events;nullonly for the handful of genuine non-period markets.
Use Cases
- Build a KPI reporting calendar or "earnings board" ranked by
newsworthiness. - Surface where Octagon's model disagrees with the market (
signal,edge_pp,edge_absolute_value) ahead of a print. - Track settled prints and surprises with
?status=reportedand the detail response'sanalysis.surprise. - Power editorial workflows directly from the
editorialblock (headline,summary,permalink). - Monitor a single company KPI across periods via the stable
kpi_id.
Examples
Today's board, desk-ranked
Python
import requests
url = "https://api.octagonai.co/v1/predictions/kpi-events"
headers = {"Authorization": "Bearer your-octagon-api-key"}
params = {"limit": 20}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
for row in response.json()["data"]:
print(f"{row['newsworthiness']:>3} {row['company_name']} — {row['kpi_name']} ({row['period_label']})")JavaScript
const params = new URLSearchParams({ limit: "20" });
const response = await fetch(
`https://api.octagonai.co/v1/predictions/kpi-events?${params}`,
{
headers: {
Authorization: "Bearer your-octagon-api-key",
},
}
);
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const { data } = await response.json();
data.forEach((row) => {
console.log(`${row.newsworthiness} ${row.company_name} — ${row.kpi_name} (${row.period_label})`);
});sh
curl -G "https://api.octagonai.co/v1/predictions/kpi-events" \
-H "Authorization: Bearer <your-octagon-api-key>" \
--data-urlencode "limit=20"Settled prints with a captured actual
Python
import requests
url = "https://api.octagonai.co/v1/predictions/kpi-events"
headers = {"Authorization": "Bearer your-octagon-api-key"}
params = {"status": "reported"}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
for row in response.json()["data"]:
actual = row["actual"]["formatted"] if row["actual"] else "—"
print(f"{row['company_name']} {row['kpi_name']}: actual {actual}")JavaScript
const params = new URLSearchParams({ status: "reported" });
const response = await fetch(
`https://api.octagonai.co/v1/predictions/kpi-events?${params}`,
{
headers: {
Authorization: "Bearer your-octagon-api-key",
},
}
);
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const { data } = await response.json();
data.forEach((row) => {
console.log(`${row.company_name} ${row.kpi_name}: actual ${row.actual?.formatted ?? "—"}`);
});sh
curl -G "https://api.octagonai.co/v1/predictions/kpi-events" \
-H "Authorization: Bearer <your-octagon-api-key>" \
--data-urlencode "status=reported"One event — full event bundle
Python
import requests
event_id = "hood_funded_customers_2026q2"
url = f"https://api.octagonai.co/v1/predictions/kpi-events/{event_id}"
headers = {"Authorization": "Bearer your-octagon-api-key"}
response = requests.get(url, headers=headers)
response.raise_for_status()
event = response.json()
market = event["prediction_market_estimate"]["central"]["formatted"]
model = event["octagon_model_estimate"]["central"]["formatted"]
print(f"Market: {market} | Octagon model: {model}")
print(event["editorial"]["headline"])JavaScript
const eventId = "hood_funded_customers_2026q2";
const response = await fetch(
`https://api.octagonai.co/v1/predictions/kpi-events/${eventId}`,
{
headers: {
Authorization: "Bearer your-octagon-api-key",
},
}
);
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const event = await response.json();
console.log(
`Market: ${event.prediction_market_estimate.central.formatted} | Octagon model: ${event.octagon_model_estimate.central.formatted}`
);
console.log(event.editorial.headline);sh
curl -s "https://api.octagonai.co/v1/predictions/kpi-events/hood_funded_customers_2026q2" \
-H "Authorization: Bearer <your-octagon-api-key>"Paginate through the board
Python
import requests
url = "https://api.octagonai.co/v1/predictions/kpi-events"
headers = {"Authorization": "Bearer your-octagon-api-key"}
cursor = None
while True:
params = {"limit": 50}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
page = response.json()
for row in page["data"]:
print(row["id"], row["status"])
if not page["has_more"]:
break
cursor = page["next_cursor"]JavaScript
const headers = { Authorization: "Bearer your-octagon-api-key" };
let cursor = null;
while (true) {
const params = new URLSearchParams({ limit: "50" });
if (cursor) params.set("cursor", cursor);
const response = await fetch(
`https://api.octagonai.co/v1/predictions/kpi-events?${params}`,
{ headers }
);
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const page = await response.json();
for (const row of page.data) {
console.log(row.id, row.status);
}
if (!page.has_more) break;
cursor = page.next_cursor;
}sh
# First page
curl -G "https://api.octagonai.co/v1/predictions/kpi-events" \
-H "Authorization: Bearer <your-octagon-api-key>" \
--data-urlencode "limit=50"
# Next page (use next_cursor from previous response)
curl -G "https://api.octagonai.co/v1/predictions/kpi-events" \
-H "Authorization: Bearer <your-octagon-api-key>" \
--data-urlencode "limit=50" \
--data-urlencode "cursor=<next_cursor_value>"Notes
- All probability values (
model_probability,market_probability,edge_pp) are percentage points on a 0–100 scale. octagon_model_estimate.central— and everything derived from it (edge_vs_market, the list row'soctagon_estimate_value/edge_absolute_value) — is the median (p50) of Octagon's model ladder, the same statistic as the market central. If you cached edge values captured before July 2026 (when the model central was a weighted mean), expect a small one-time shift; edgedirectionnow never contradictsprobability_signal.edge_pp.- Never parse
formattedstrings for computation — use thevaluefield of eachKpiValueobject. - An event under
?status=settledmay not yet have anactual; use?status=reportedwhen you need trusted actuals only. near_settled: truemeans the market is effectively decided (probability ≥97% or ≤3%) — treat any remaining edge as settlement noise, not signal.