---
name: finance-analytics
description: Use this skill when the user wants to analyze financial performance, review P&L health, monitor MRR/ARR, investigate margin or cost trends, build a finance report, check cash flow or runway, or answer questions about their accounting/billing data. Triggers include 'how is revenue trending', 'gross margin', 'MRR breakdown', 'churn impact on ARR', 'why did costs go up', 'operating expenses', 'cash runway', 'P&L review', 'EBITDA', 'cost per acquisition trend', 'pull my QuickBooks numbers', 'finance report'.
metadata:
  title: "Finance Analytics"
  short_description: "Shows your P&L, MRR, margins and cash runway, pulled straight from your accounting and billing tools."
  category: finance
  sources:
    - QuickBooks
    - Xero
    - Oracle NetSuite
    - Stripe
    - Sage
---

# Finance Analytics

Shows your P&L, MRR, margins and cash runway, pulled straight from your accounting and billing tools. Finance Analytics is a Coupler.io AI agent skill that works with live data from QuickBooks, Xero, Oracle NetSuite, Stripe, and Sage.

Analyze financial performance using data from Coupler.io dataflows (QuickBooks, Xero, Stripe, NetSuite, Sage, billing systems). This skill guides you through retrieving accounting and revenue data, computing P&L, margin, subscription, and cash metrics, detecting anomalies, and presenting actionable insights a finance lead can act on.

## Step 0: Context Check (Pre-requisite · HARD GATE)

**Before any analysis, confirm the user has a live Coupler.io connection to their finance data.** No live connection, no analysis — no pasted P&L screenshots, no numbers from memory or a prior conversation, no benchmarking against industry averages instead of the user's actual QuickBooks, Xero, NetSuite, Stripe, or Sage data. Unsure counts as no.

If no data source is connected, stop and hand off to the `create-dataflow` skill to connect one — don't re-implement the connection flow here.

Before starting any analysis, the **Data Context Check** skill (`generate-data-set-context`) runs as a gate. It calls `get-schema` on each target dataset to determine whether meaningful context (chart of accounts mapping, entity/subsidiary structure, currency conventions, fiscal calendar, accrual vs. cash convention) is attached.

- If context exists → proceed to Step 1.
- If context is missing → the user is offered the option to generate it first.

Do not duplicate this check in Step 1d.

## Step 1: Discover and Select Data Sources

### 1a. Discover available data

Default to `search-datasets` with finance-flavored keywords — `quickbooks`, `xero`, `netsuite`, `stripe`, `sage`, `gl`, `invoice`, `revenue`, `mrr`, `arr`, `bank`, or whatever system the user named. Search keeps the response small and lands on the right dataflow when the domain is known.

Fall back to `list-datasets` only when the user is genuinely browsing or hasn't given any source/keyword to anchor on. Each dataflow represents a data pipeline (e.g. "QuickBooks GL", "Stripe Charges", "NetSuite Revenue", "Xero Invoices", "Bank Transactions").

### 1b. Select relevant datasets

**Unambiguous match (1 dataflow)** → use it; mention which one.

**Obvious candidates (2–3)** → state your selection with one-line reasoning, proceed but invite corrections.

**Ambiguous (5+, or unclear)** → present best candidates (up to 5–7) grouped by source/scope, with reasoning, and wait for confirmation:

```
I found 3 dataflows likely relevant to your MRR question:
  1. stripe_subscriptions — has plan, MRR amount, status
  2. quickbooks_gl — has revenue accounts, but at journal grain
  3. salesforce_opportunities — has booked ARR, less useful for recognized
Should I use Stripe alone, or combine Stripe and QuickBooks for cross-check?
```

**Hard gate only when ambiguous.** If you're confident and stated reasoning, proceed.

### 1c. Get dataflow details

Call `get-dataflow` for each candidate. Note `schedule` (data freshness), source health, and the close status of any GL data — finance refreshes are often slower than transactional sources.

### 1d. Understand the data structure

Call `get-schema` on each target dataset. If context was generated in Step 0, use the enriched schema directly.

For finance schemas, watch for these critical column families: account/account_code (chart of accounts), entity_id/subsidiary, currency, transaction_date/posting_date, amount (signed: positive = credit, varies by source), invoice_status (paid/open/voided), customer_id, plan_id, billing_period_start/end, refund flags.

### 1e. Sample the data

Sample each dataset to verify contents. Watch specifically for: signed-amount conventions (debit-positive vs. credit-positive), currency mixing, journal entry duplicates, voided/reversed entries that need exclusion. Flag anything off before proceeding.

## Coverage Verdict (say this out loud before analysing)

Tell the user which parts of this analysis the connected data can actually support before computing anything — it decides what the rest of the run can credibly say.

| Data area | If present, enables | If absent, means |
|---|---|---|
| GL/journal-level detail (vs. summary P&L rows) | Cost-center drill-down by sub-account or vendor | Cost-Center Investigation can only run at the category level — say so, don't fabricate a vendor-level split from summary rows |
| Bank/cash transaction data | Cash burn and runway calculations | Say bank/cash data isn't in scope. Don't extrapolate runway from P&L data without it |
| Multi-entity/subsidiary structure | Proper consolidation across entities and currencies | Don't sum across entities without knowing the structure — say consolidation can't be verified, or state the single-entity assumption used |
| Budget/plan data | Actual-vs-budget comparisons | Budget figures usually don't live in QuickBooks, Xero, NetSuite, or Stripe — say budget comparison isn't available unless the user supplies it or a budget dataflow is connected |
| Close status (preliminary, soft-closed, hard-closed) | Confidence that period-end numbers are final | Treat pre-close numbers as provisional and say so before presenting them |

Any row marked absent is one more Coupler.io source or context field away — tell the user what to connect rather than working around the gap silently.

**Early exit.** If only summary-level or partial data is connected, run the parts the coverage table supports, state plainly which sections were skipped and why, and don't backfill the gap with assumptions or industry benchmarks.

## Step 2: Compute Metrics via SQL

Always compute via SQL in `get-data`. Floating-point aggregations over thousands of rows in-context are unreliable.

### Working with multiple datasets

**Combining datasets:** `get-data` reads one dataset at a time and cannot join across them. Query each separately and synthesize when you are comparing side by side or pulling something small. When the user wants to repeat an analysis that needs a real join (matching rows across datasets, or aggregating over the combined result), build it with `create-dataset` so it re-runs on every refresh; its inputs must all live in the same dataflow. For a one-off question, combine the results yourself, and if the data is too large for that, say so and suggest `create-dataset`.

**Date alignment:** Posting date vs. transaction date vs. service date can differ — confirm which the user wants. Use fiscal calendar if the company doesn't operate on calendar months.

**Currency normalization:** Multi-entity companies need consolidation; always state your conversion approach (period-end FX vs. average FX vs. native).

**Cash vs. accrual:** Critical distinction. Confirm which convention the user wants. Stripe data is mostly cash; QuickBooks/NetSuite GL can be either depending on configuration.

**Recognized vs. booked:** Booked = contract signed (Salesforce). Billed = invoice issued. Recognized = ASC 606 revenue recognition (subscription pro-ration). Don't conflate; ask if unclear.

**Voided/reversed entries:** GL data often includes voided journals — exclude them in the WHERE clause. Don't double-count refunds as new revenue.

## Step 3: Draft Findings and Get User Feedback

Before generating a full analysis, present a brief summary — the 3–5 most important numbers, anomalies, and direction. Wait for user response before continuing.

## Step 4: Build the Analysis

### P&L Review

Standard structure: Revenue → COGS → Gross Profit → Operating Expenses → Operating Income → Other → Net Income.

- **Gross margin %** = (Revenue − COGS) / Revenue. Track period-over-period; a 2-point compression is meaningful.
- **Operating margin %** = Operating Income / Revenue.
- **Expense breakdown by category** (Sales & Marketing, R&D, G&A) — flag categories growing faster than revenue.
- Period-over-period and year-over-year comparisons. State the comparison basis explicitly.

Flag concentration: if one customer/product is >20% of revenue, call it out as a concentration risk.

### MRR / ARR & Subscription Health

For SaaS or subscription businesses:

- **MRR** = sum of monthly recurring revenue across active subscriptions. ARR = MRR × 12.
- **MRR movement bridge**: Starting MRR + New + Expansion + Reactivation − Contraction − Churn = Ending MRR. Always reconcile the bridge — gaps reveal data issues or missing categories.
- **Net Revenue Retention (NRR)** = (Starting MRR of cohort + Expansion − Contraction − Churn) / Starting MRR. Healthy SaaS: >100%.
- **Gross Revenue Retention (GRR)** = (Starting MRR − Contraction − Churn) / Starting MRR. Excludes expansion.
- **Logo churn vs. revenue churn** — present both; high logo churn with stable revenue churn signals SMB churn masked by enterprise stability.

### Cash & Runway

- **Cash burn (monthly)** = avg monthly net cash outflow over trailing 3 months.
- **Runway** = current cash balance / monthly burn. State both calendar months and 'months at current burn'.
- **Operating cash flow vs. net income** — divergences signal AR/AP timing issues.

If bank/cash data isn't in scope, say so. Don't extrapolate runway from P&L data without cash data.

### Cost-Center Investigation

When the user asks 'why did costs go up' or 'where is spend growing fastest':

1. Break down the cost category by sub-account or vendor.
2. Compare to prior period at the sub-account level.
3. Identify the top 3 sub-accounts driving the change.
4. Check for one-time items (annual renewals, project spikes) vs. structural increases.
5. Present: "Of the $X increase, $Y is from <vendor/account> renewing on annual cycle, $Z is structural increase in <category>, balance is distributed."

### Anomaly Detection and Metric Investigations

Any time the analysis involves investigating a change, drop, or spike — apply this framework:

**Severity classification:**
- **Informational** — within 1 SD of trailing 4-month average, or <5% change. Note it.
- **Warning** — 1–2 SD, or 5–15% change. Investigate, present hypotheses.
- **Critical** — >2 SD, >15% change, or any metric crossing a covenant/threshold. Lead with this finding.

Finance has tighter sensitivity than marketing/ecom — a 10% gross margin drop is a 'critical' event, not 'warning'.

**Baseline comparison:** Same period prior year (annual seasonality matters in finance), trailing 3-month average, budget if available.

**Root cause investigation steps:**
1. **Isolate the scope** — which entity, which account, which customer/vendor.
2. **Check posting period** — late-arriving journals, period-end accruals, reversal entries.
3. **Check upstream changes** — pricing changes, contract renewals, vendor changes, new accounting policy.
4. **Check for data issues** — duplicate journals, currency conversion errors, voided entries not excluded.
5. **Present hypotheses ranked by likelihood** — "Most likely: annual security audit fee posted to G&A in this month vs. amortized last year. Less likely: structural growth in headcount cost."

## Step 5: Present Results

Lead with the headline, use plain language, ensure every finding has a 'So what?' and 'Now what?', structure for scannability.

**Abbreviation expansion:** First use of MRR, ARR, NRR, GRR, EBITDA, COGS, GAAP, ASC 606, AR, AP, FX — expand it.

**Currency:** Always state on first use. If multi-currency, state your normalization approach (period-end vs. average FX, source of rates).

**Materiality:** Note material vs. immaterial movements. A $5 swing in a $50M revenue line is noise.

## Rules & Edge Cases

- Always state data freshness and the close status (preliminary, soft-closed, hard-closed) before presenting numbers. Pre-close numbers can shift materially.
- State revenue convention (cash, accrual, recognized) on first use; never silently switch.
- Voided/reversed journals must be excluded from totals. If you can't tell which entries are voided, say so.
- Multi-entity / multi-currency: never sum across entities without consolidation. State your consolidation approach.
- Prior-period adjustments and reclassifications: if a prior month was restated, mention it — comparing current period to a restated prior gives different results than to the original.
- Round to materiality: don't report margins to 4 decimals when 1 decimal is enough. Don't report dollar amounts to the cent on totals over $10K.
- Tax: distinguish pre-tax and post-tax metrics explicitly when both exist.
- If a dataflow's last execution failed or is stale (>2 days for a daily GL refresh), warn the user — and consider that GL data is often refreshed less frequently than transactional sources, so 'stale' definitions differ.

## Next Question (REQUIRED)

Exactly one, drawn from what this run found. Never a menu — a second only when the data genuinely points two ways.

- "Gross margin compressed from 61% to 58% quarter-over-quarter — want me to drill into the cost centers driving that 3-point drop?"
- "The MRR bridge doesn't reconcile — Starting + New + Expansion − Contraction − Churn lands $12K short of Ending MRR — want me to trace the gap to find the missing category?"
- "Runway is at 8 months at the current burn rate — want a deeper look at operating cash flow vs. net income to check whether AR timing is inflating the burn?"
