How to Use n8n with ._Template 78 Monthly Revenue Report

Every month, someone on your team opens Stripe, exports a CSV, pastes it into a spreadsheet, cross-references refunds, calculates MRR growth, and rebuilds the same revenue summary they built last mont

How to Use n8n with ._Template 78 Monthly Revenue Report

Every month, someone on your team opens Stripe, exports a CSV, pastes it into a spreadsheet, cross-references refunds, calculates MRR growth, and rebuilds the same revenue summary they built last month. It takes two to four hours, it happens the same week every month, and by the time the report lands in the founder's inbox the numbers are already stale. The Monthly Revenue Report template for n8n replaces that entire ritual with a workflow that runs on a schedule, pulls live data from your payment processor, computes the metrics that actually matter, and delivers a formatted report — no human in the loop.

The problem: manual revenue reporting doesn't scale

Manual revenue reporting fails in three predictable ways. First, it's inconsistent — the person who builds the report defines the metrics, so when they're on vacation the format changes or the report simply doesn't ship. Second, it's error-prone — copy-pasting between Stripe exports and Google Sheets introduces off-by-one rows, timezone mismatches on the reporting window, and double-counted refunds. Third, it's slow to react — a monthly cadence built by hand means you find out about a churn spike three weeks after it started.

The underlying issue is that revenue data lives in one system (Stripe, Paddle, Chargebee), the calculations live in a spreadsheet, and the audience lives somewhere else entirely (email, Slack, a Notion dashboard). Every handoff between those systems is manual, and every manual handoff is a place where the process breaks. What you need is a single pipeline that connects the source of truth directly to the people who read it.

The solution: a scheduled n8n workflow

n8n is a fair fit for this because revenue reporting is fundamentally an ETL job on a timer: extract transactions from an API, transform them into metrics, load the result into a report and a delivery channel. The Monthly Revenue Report template wires that up as a linear workflow you can read top to bottom.

At a high level the workflow does five things: it triggers on the first of the month, queries your payment processor for the previous month's charges and refunds, aggregates those transactions into MRR, new revenue, churned revenue, and net growth, formats the numbers into an HTML table, and pushes the result to email and Slack. Because every step is a node, you can swap the data source or the delivery channel without rebuilding the logic in the middle.

Step-by-step setup in n8n

Here is how the template is assembled. If you're building it from scratch rather than importing the JSON, this is the node sequence to replicate.

1. Schedule Trigger. Add a Schedule Trigger node set to a Cron expression of 0 6 1 * * — 06:00 on the first day of every month. Set the node's timezone explicitly (Settings → Timezone on the node, or the workflow default) so your reporting window doesn't drift by a day when the server runs UTC and you report in local time.

2. Compute the reporting window. Add a Code node (JavaScript) immediately after the trigger. Use it to calculate the first and last epoch timestamps of the previous month, since that's the period you're reporting on:

const now = new Date();
const start = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const end = new Date(now.getFullYear(), now.getMonth(), 1);
return [{ json: { gte: Math.floor(start/1000), lt: Math.floor(end/1000) } }];

3. Pull transactions. Add the Stripe node (or an HTTP Request node if you're on a processor without a native integration). Use the Charge → Get Many operation, enable Return All so pagination is handled for you, and pass a filter of created[gte] and created[lt] using the timestamps from the Code node. Add a second Stripe node for the Refund → Get Many operation over the same window. Store your API key in n8n Credentials — never hardcode it in an HTTP node's header.

4. Aggregate into metrics. Feed both branches into a Merge node (mode: Combine) or route them into a single Code node that reduces the transactions into your KPIs. This is where you sum gross revenue, subtract refunds for net revenue, count new versus recurring customers, and compute month-over-month growth by comparing against last month's stored figure. If you want a running comparison, read the prior month's total from a Google Sheets or Postgres node before this step and write the current total back after.

5. Format the report. Add a Set (Edit Fields) node or another Code node to build an HTML table from the metrics — one row per KPI, with the value and the percentage change. Keeping formatting in its own node means you can restyle the report without touching the math.

6. Deliver. Branch the formatted output into a Send Email node (SMTP or Gmail) with the HTML body, and an HTTP Request or Slack node posting a condensed version to your revenue channel. Wrap the delivery nodes so that a failure in one doesn't block the other.

Once the nodes are connected, run the workflow manually with Execute Workflow to validate the numbers against a known month before you trust the schedule. Then activate it.

The benefits: consistency, speed, and a single source of truth

The immediate win is time — a report that took a half-day now costs zero recurring effort. But the more valuable outcome is consistency. The metric definitions are frozen in the Code node, so MRR means the same thing every month regardless of who's around. That makes the trend line trustworthy, which is the whole point of a monthly report.

You also get freshness. Because the workflow reads live from the Stripe API rather than a stale export, the report reflects the actual close of the month, including late-settling charges. And because n8n logs every execution, you have an audit trail: if a number looks wrong, you can open the exact run, inspect the raw API response, and see precisely which transactions produced the figure. That's a level of traceability a spreadsheet never gives you.

Finally, the workflow is composable. Once revenue data flows through n8n on a schedule, adding a quarterly board deck, a churn alert, or a cohort breakdown is a matter of branching off the existing aggregation node rather than starting a new manual process.

Common pitfalls to avoid

Timezone drift. The single most common bug is a reporting window that's off by a day because the Schedule Trigger runs in UTC while your Code node computes dates in local time. Pin the timezone on both the workflow and any date math, and test around a month boundary.

Ignoring pagination. Stripe returns 100 objects per page by default. If you forget Return All on the charge query, a high-volume month silently under-reports revenue and nobody notices because the report still "looks right." Always paginate, and sanity-check the transaction count against your dashboard.

Counting refunds and disputes wrong. Gross charges are not revenue. Subtract refunds, and decide explicitly whether to net out disputes and processing fees — document that choice in a comment inside the Code node so the definition is visible.

No error handling. An API timeout on the first of the month means no report and no signal that anything failed. Set the workflow's Error Workflow in settings, or add an error branch that pings Slack, so a silent failure becomes a loud one.

Hardcoded secrets. Putting the Stripe key directly in an HTTP node's header leaks it into exports and execution logs. Use n8n Credentials so the secret is encrypted and never serialized into the workflow JSON you share or back up.

Get these five right and the Monthly Revenue Report becomes the kind of automation you forget exists — until you realize you haven't built a revenue report by hand in a year.