Sync KPIs
Four ways to land KPI period values in BoardHerald — webhook, Stripe forwarder, MCP cron, or CSV upload. Pick whichever matches the tool that already owns the data.
KPIs in BoardHerald are time-series — every period (monthly, quarterly, ad-hoc) is one row. The board sees the latest value, a sparkline of the last six periods, period-over-period delta, and an on-track / at-risk / off-track badge against the target window. Once the values are landing, the rest is automatic.
The five entry points below all upsert the same KpiPeriod row, so a value pushed via the built-in Stripe connector is indistinguishable from one entered by hand. Pick whichever fits the source system; mix and match freely.
1. Built-in Stripe connector (recommended for MRR)
The fastest path for revenue metrics. Connect once at Admin → Integrations → Connect Stripe (paste a restricted API key with Subscriptions: Read), then bind a KPI to a metric on the KPI's detail page. Three metrics ship today: active_subscription_mrr, active_subscriptions_count, and trialing_subscriptions_count. The daily KPI sync cron picks up the binding and refreshes the current period — no glue code on your side.
Use the "Sync now" button on the binding panel to verify the value before waiting for the cron tick.
2. Webhook (one period at a time)
The simplest entry point. POST a single value, identify the KPI either by kpiId or by (sourceSystem, externalId). Both fields can be set on the KPI from the "Link to external source" collapsible in the new-KPI form.
POST https://app.boardherald.com/api/kpis/webhook
Authorization: Bearer bh_REPLACE_WITH_YOUR_KEY
Content-Type: application/json
{
"sourceSystem": "stripe",
"externalId": "metric_mrr",
"periodStart": "2026-04-01",
"value": 42000,
"note": "April MRR snapshot"
}200 OK
{
"ok": true,
"kpiId": "9b2e…",
"periodId": "f1a3…",
"periodStart": "2026-04-01T00:00:00.000Z",
"value": "42000",
"isNewLatest": true
}kpis:webhook scope. Issue it from Profile → API Keys with only that scope ticked — narrower than financials:write, which would let the agent rewrite KPI metadata too.Re-posting the same (kpi, periodStart) silently overwrites the value. That makes the endpoint idempotent for cron retries; for an audited correction (the value changed for a reason worth recording), use the kpis_restate MCP tool instead.
3. Custom Stripe forwarder (when the built-in metric isn't the one you want)
The built-in Stripe connector covers active subscription MRR + counts. If your definition of "MRR" is different (different currency conversion, plan exclusions, prorations) it's usually faster to fork the computation into your own webhook handler than to ask us for a config knob.
// One-shot Node script you can wire to a Stripe webhook.
// Subscribe to invoice.paid + invoice.payment_failed in
// the Stripe dashboard, point them at your endpoint, and
// forward the running MRR total to BoardHerald.
import Stripe from "stripe";
export async function forwardMrrToBoardHerald(stripe: Stripe) {
// Sum live subscriptions; this is the "today" snapshot.
const subs = await stripe.subscriptions.list({
status: "active",
limit: 100,
});
const mrr = subs.data.reduce((sum, s) => {
return sum + (s.items.data[0]?.price.unit_amount ?? 0);
}, 0) / 100;
await fetch("https://app.boardherald.com/api/kpis/webhook", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.BOARDHERALD_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
sourceSystem: "stripe",
externalId: "metric_mrr",
periodStart: new Date().toISOString().slice(0, 10) + "-01",
value: mrr,
}),
});
}The KPI itself is created once in BoardHerald (Admin → KPIs → New KPI), with sourceSystem="stripe" and externalId="metric_mrr" set under "Link to external source". After that, every push lands without any manual mapping.
4. MCP cron job
For data that lives in another internal tool — a database, a Notion page, a custom dashboard — call the existing kpis_record_period MCP tool from a scheduled job. Same authentication path Claude Desktop uses; easier to reason about than a separate webhook because all KPI tools live under the same scope namespace.
# Run this once a day (e.g. cron, GitHub Actions schedule,
# Railway scheduled job). Uses the MCP bridge to record a
# value via the same kpis_record_period tool admins use in
# the UI.
npx -y @boardherald/mcp-bridge \
--api-key "$BOARDHERALD_KEY" \
--url "https://app.boardherald.com" \
--tool kpis_record_period \
--json '{
"kpiId": "9b2e…",
"periodStart": "2026-04-01",
"value": 42000,
"note": "Daily MRR roll-up"
}'Use a separate API key for the cron with only financials:write ticked. Rotating it doesn't touch your interactive Claude key.
5. CSV upload
For one-off backfills, period-over-period imports from a spreadsheet, or hand-curated history that predates the tooling — paste a CSV at Admin → KPIs → Import CSV. Same upsert semantics as the webhook (silent overwrite on collision); rows whose KPI name doesn't resolve are reported back per-row so you can fix and re-upload.
kpiName,periodStart,value,note MRR,2026-01-01,42000,Q1 kickoff MRR,2026-02-01,45500, MRR,2026-03-01,48200,Pricing change shipped Headcount,2026-01-01,18,Hired 2 engineers Headcount,2026-02-01,19, Runway months,2026-01-01,14,Updated cash forecast
The header row is required (kpiName, periodStart, value; optional note). KPI name must match exactly — the display-name override doesn't apply on import. Max 1,000 rows per batch.
Picking the right entry point
- Built-in Stripe connector — default for MRR / subscription counts. Zero glue code; the cron does the work.
- Webhook — when the source already emits webhooks (GitHub, Linear, Zapier). Cheapest plumbing for non-Stripe sources.
- Custom Stripe forwarder — when the built-in metric definition doesn't match your board's convention.
- MCP cron — when the source needs auth you don't want to surface (a private DB, an internal API). The MCP key + scoped role keep the blast radius small.
- CSV upload — historic backfills, one-off corrections, or hand-curated metrics that don't have a system of record yet.
Next
- Configure the connector key: Configuration
- Scope reference: Capabilities
- What the board sees: Financials