KPIs
Live indicators of organizational performance — pinned to every member's home, kept current automatically by connectors.
Last updated
KPIs are the live indicators of how your organization is performing — uptime, ARR, NPS, latency, churn, win rate. The numbers leaders use to know whether the business is actually working right now. In Mistvine, KPIs are pinned on every member's Home and kept current automatically by connectors.
KPIs vs Goals
KPIs are indicators of performance. They're continuous — you keep watching them. Goals (OKR objectives and key results) are what you're trying to achieve in a specific cycle. Goals usually point at where you want a KPI to move; the KPI tells you whether it's actually moving.
You don't need both for everything, but they answer different questions. A goal sets direction; a KPI tracks reality.
Who can see and manage them
| Role | Can do |
|---|---|
| Admin | Publish, edit, delete KPIs; bind connectors; rotate webhook secrets |
| Member | View all published KPIs on Home |
KPIs are intentionally org-wide and visible to everyone. The headline numbers your company runs on belong on every member's home screen — not behind a BI seat.
Manage KPIs at Settings → KPIs.
The four indicator types
Real KPIs don't all behave the same way. Mistvine supports four indicator shapes — pick the one that matches how the metric actually behaves.
Stay above
A floor the indicator must hold. Status flips red the moment current value falls below the threshold.
- Configure: a single goal value (the floor)
- Use for: NPS, uptime, CSAT, win rate, customer retention, gross margin
- Example: "Uptime stay above 99.9%" — current 99.94% → green; if it drops to 99.85% → red
Stay below
A ceiling the indicator must hold. Status flips red the moment current value exceeds the threshold.
- Configure: a single goal value (the ceiling)
- Use for: latency, MTTR, churn rate, defect escape rate, support ticket backlog
- Example: "p95 API latency stay below 500ms" — current 380ms → green; if it climbs to 580ms → red
Stay between
A healthy range the indicator must stay inside. Both ends matter — too low or too high signals a problem.
- Configure: a lower bound and an upper bound
- Use for: sessions per active user, conversion rate, headcount growth rate, inventory turnover
- Example: "Sessions per user / week between 3.0 and 7.0" — current 4.2 → green; current 1.8 (disengagement) → red; current 9.5 (possible burnout) → red
Trend
Direction-only — the indicator should be moving up or down compared to a prior-period baseline. No fixed threshold.
- Configure: a direction (up or down) and a baseline value
- Use for: ARR, MAU, signups, average deal size (direction up); churn rate, time-to-first-value, cost-per-acquisition (direction down)
- Example: "ARR trending up from $1.2M" — current $1.84M → green; if it drops back to $1.1M → red
When to use trend instead of stay-above / stay-below: if there's no specific number that's "good enough" — you just want the metric heading in your favor against your prior performance — use
trend. ARR doesn't have a threshold; it just needs to keep going up.
Quick-create syntax
The KPI title field auto-detects shape and target as you type. Examples:
| Type the title | Detected shape |
|---|---|
NPS above 35 |
stay_above, threshold 35 |
Keep MTTR below 4h |
stay_below, threshold 4h |
Sessions per user between 3 and 7 |
stay_between, range 3–7 |
ARR trending up |
trend, direction up |
Churn trending down |
trend, direction down |
When the parser detects a shape, an "Apply" suggestion appears below the title — click it and the form fields fill in automatically.
Display formatting
Each KPI has a unit_type and display_format that control how the value renders:
unit_type |
Renders as | Example |
|---|---|---|
currency (with unit_label = ISO code, e.g. USD/EUR/GBP) |
$1,840,000 / €42,500 |
locale-formatted with currency symbol |
percentage |
99.94% |
value is treated as already-a-percent |
time (with unit_label like "ms" or "h") |
380 ms, 4.5 h |
numeric + unit |
number |
47, 4.6 / 5 |
thousands separators; unit_label appended |
boolean |
Yes / No |
based on whether value is truthy |
display_format controls decimal places: integer (none), decimal_1, decimal_2, percentage.
Connectors — keeping KPIs current automatically
Four connector types ship today. Each KPI can use one (and only one) at a time. The same connector model also feeds OKR key results — wire the data once at the source of truth, and every surface that depends on the indicator stays in sync.
Manual
The default. Admins update the current value inline by clicking the number in the KPI list. Good for metrics that don't have a programmatic source, or as a fallback when a connector breaks.
Google Sheets
Bind a KPI to a specific cell in a spreadsheet. Mistvine reads only that cell on a schedule — no broader Drive access.
- Connection scope: per-user. Each admin authorizes their own Google account at Profile → Connections. Other users in the org (including other admins) cannot see your Drive or your other sheets.
- What you bind: spreadsheet → tab → cell (A1 notation, e.g.
B12) - Refresh cadence: scheduled cron, runs throughout the day
- Good for: numbers your finance, ops, or analytics team already maintains in Sheets
Webhook
Mistvine mints a per-KPI HMAC-signed POST endpoint. Your system pushes a value to that URL, signed with the secret you receive once at mint time.
- Endpoint:
https://<supabase-url>/functions/v1/kpi-source-receive/<kpi-id> - Refresh cadence: real-time — the KPI updates the moment the POST lands
- Secret rotation: rotate from the KPI list at any time; old secret invalidates immediately
- Good for: real-time signals like incident counts, signups, deploys
HTTPS GET
Mistvine polls a URL on a schedule, parses JSON, and extracts a value via JSON path.
- What you provide: a public HTTPS URL, an optional bearer token, and a JSON path (e.g.
$.valueor$.data.metrics.uptime) - Refresh cadence: scheduled cron, runs throughout the day
- Defenses: server-side URL validation (no loopback / private IPs / non-HTTPS / reserved hostnames)
- Good for: status pages, monitoring tools, or any service exposing a metric over HTTPS
What happens when a KPI drifts
When a KPI crosses its threshold, range, or expected direction, its status indicator on Home changes color (green → red). That's it — no email blasts, no pages, no auto-Slack. The signal is visual presence on a surface people already use. No alert fatigue, no inbox noise.
What happens when a connector breaks
Mistvine keeps showing the last-known value with a "last pulled" timestamp, and the failed-pull error is recorded so an admin can debug. You can switch the source back to manual at any time and edit the value inline — no support ticket, no admin-only RPC.
FAQ
Can a KPI's history be exported?
History is recorded in org_kpi_history whenever the value changes. Export tooling is on the roadmap; today the data is queryable via the Supabase API for tenant admins.
Can two KPIs share the same connector? Each KPI binds to its own source independently. If two KPIs read from the same Sheets cell or the same HTTPS endpoint, that's allowed — they just refresh independently.
Can I change a KPI's type after it's published?
Yes — but it's a structural change. Switching from stay_above to trend will require you to set a baseline and direction. Existing history rows aren't rewritten, but the status calculation for new values uses the new shape.
Are KPI changes audit-logged? Yes — every value write, type change, and connector configuration change is logged via the platform-wide audit infrastructure.
Do KPIs replace a BI tool? No. Mistvine pins the small set of metrics your whole organization should be watching. BI tools remain the right place for slice-and-dice exploration, drill-downs, and ad-hoc analysis. Think of KPIs as the headline numbers everyone in the company should know without needing a BI seat to find them.