All Projects
Finance

Automated Weekly Financial Report for Executives

Every Monday, someone spent 2-3 hours pulling numbers from Stripe, QuickBooks, and Sheets. Now a scheduled pipeline aggregates everything into a rich HTML executive email automatically.

Cost savings

$4,200/mo saved

Cost savings

$4,200/mo

Time saved

2-3 hrs/week

Tools
StripeQuickBooksGoogle SheetsGmailn8n

The Client's Problem

My Approach

The Workflow Breakdown

1

Schedule Trigger fires every Monday at 6:00 AM EST. A cron expression (`0 6 * * 1`) initiates the pipeline at the start of the business week. The trigger is timezone-aware and fires reliably regardless of daylight saving time transitions.

2

Stripe Charges API call pulls the last seven days of revenue. An HTTP Request node calls `GET /v1/charges` with `created[gte]` and `created[lte]` query parameters calculated dynamically from the current timestamp. The request filters for the trailing seven-day window and paginates up to 100 charges. Authentication uses Stripe's bearer token via a stored credential.

3

Stripe Refunds API call captures all refunds in the same window. A second HTTP Request pulls `GET /v1/refunds` with the same date range. This is kept as a separate call rather than embedded in the charges query because Stripe's API treats refunds as a distinct resource, and separating them makes the net revenue calculation explicit and auditable.

4

Stripe Subscriptions API call retrieves all active subscriptions. A third Stripe call to `GET /v1/subscriptions?status=active` returns the current subscription base. The KPI engine uses this to calculate MRR by summing `plan.amount * quantity` across all active subscriptions, which is more accurate than inferring MRR from weekly charge volume.

5

QuickBooks Profit & Loss report provides categorized expenses. An HTTP Request calls the QuickBooks Online Reporting API with the same trailing seven-day window and accrual accounting method. The response breaks expenses into categories -- payroll, hosting, software, marketing, cost of goods sold -- which feed directly into the expense breakdown table and gross margin calculation.

6

Google Sheets reads current team metrics. A Google Sheets node pulls from the HR-maintained "Team Metrics" sheet, capturing headcount, new hires, departures, and open roles. This data drives the per-employee revenue calculation and the team snapshot section of the email.

7

Google Sheets reads previous week's archived KPIs. A second Sheets read pulls the most recent row from the "Weekly KPI Archive" tab -- the same sheet that the workflow writes to at the end of each run. This creates a self-referencing loop where each week's report automatically compares against the prior week's numbers without any manual baseline management.

8

KPI Calculation Engine processes all upstream data. A Code node containing approximately 120 lines of JavaScript ingests data from all five upstream sources and produces a comprehensive KPI object. It calculates gross revenue, net revenue (after refunds), refund rate, MRR, ARR, active subscription count, average transaction value, total expenses by category, gross margin, operating margin, monthly burn rate, adjusted cash runway, revenue per employee, and week-over-week growth percentages for every applicable metric. The node also tracks data source health, recording which APIs responded successfully and which returned errors.

9

Anomaly Detection Engine flags significant week-over-week changes. A second Code node compares each KPI against the previous week's values. Any metric that changed more than 15% is flagged and classified: revenue increases and expense decreases are labeled "improvement," while revenue decreases and expense increases are labeled "concern." Each anomaly receives a severity rating -- low (15-20%), medium (20-30%), or high (30%+). The engine also flags structural anomalies like a single expense category exceeding 40% of total spend, elevated refund rates above 5%, or cash runway dropping below six months.

10

Conditional routing checks for data source failures. An IF node evaluates the `allSourcesHealthy` flag from the KPI engine. If any upstream API returned an error, the workflow routes to a partial report builder. If all sources responded successfully, it proceeds directly to HTML email generation.

11

Partial Report Builder handles degraded data gracefully. When triggered, this Code node modifies the KPI object by replacing metrics from failed sources with explicit `[DATA UNAVAILABLE]` markers. It generates a list of which sources failed and constructs a warning message that appears as a prominent amber banner at the top of the email. The executive team sees exactly what data is missing and why, rather than receiving nothing or receiving misleading zeros.

12

HTML Email Builder generates a professional executive report. The largest Code node in the workflow -- roughly 200 lines -- constructs a fully inline-styled HTML email optimized for email client rendering. The email includes a branded header with the report date range, a revenue summary table with week-over-week change arrows (green up-arrows for growth, red down-arrows for decline), a categorized expense breakdown with percentage-of-total columns, six KPI cards showing gross margin, operating margin, burn rate, runway, revenue per employee, and subscription count, a team snapshot bar, and an anomaly alert section with color-coded badges. All currency values are formatted with proper locale separators. The footer includes data freshness timestamps and source attribution.

13

Gmail sends the report to the executive distribution list. A Gmail node delivers the HTML email to the CFO, finance team, and COO. The subject line dynamically includes the date range and appends a warning indicator if any anomalies were flagged as concerns, or a `[PARTIAL]` prefix if data sources were unavailable.

14

Google Sheets archives this week's KPIs for historical tracking. After successful delivery, a Sheets append operation writes all calculated KPIs to the "Weekly KPI Archive" tab. This row becomes the comparison baseline for next week's report and enables the executive team to build their own trend charts and dashboards on top of the accumulated data.

15

Error Trigger catches any unhandled workflow failures. A separate error handling branch activates if the workflow throws an unrecoverable exception. A Code node extracts the error message, failed node name, execution ID, and timestamp, then formats a structured Slack message. The Slack node posts to #finance-ops with the error details, a direct link to the failed execution in n8n, and a clear statement of the business impact -- that the weekly report may not have been delivered.

Results & Impact

  • Monday report delivery: moved from 11:00 AM (after 2-3 hours of manual work) to
  • Preparation time: reduced from 2-3 hours of CFO time every Monday to zero human
  • Data accuracy: 100% since deployment. Eliminated all manual transposition errors,
  • Anomaly detection: the 15% threshold catches week-over-week shifts that the CFO
  • CFO time reclaimed: approximately 10-12 hours per month, redirected from data
  • Report reliability: the graceful degradation design has been tested in production
  • Historical trending: after 12 weeks of archived KPI data, the finance team built

Technical Highlights

  • Graceful degradation architecture: every external API call is configured with
  • Self-referencing historical comparison: the workflow reads from and writes to the
  • Automated anomaly detection with smart classification: the detection engine goes
  • Production-grade HTML email rendering: all styling is inline CSS for maximum email
  • Idempotent weekly execution: the workflow uses date-range-based data pulls calculated
  • Separation of concerns in Code nodes: data aggregation, anomaly detection, partial

Tools Used