n8n runway forecast automation: Daily cash‑flow charts

RRahul Soni · September 26, 2026 · 14 min read

AnswerIn this n8n runway forecast automation tutorial we show how to pull accounting data, compute runway and burn rate, create a live cash‑flow chart, and email the forecast each morning. The guide covers QuickBooks, Xero, chart customization, alerts, and security for founders.

  • Connect QuickBooks or Xero to n8n in minutes
  • Calculate runway and burn rate with built‑in functions
  • Generate a PNG cash‑flow chart with n8n’s Chart node
  • Schedule a daily email with the chart attached
  • Add low‑runway alerts and secure your financial data

How to connect your accounting software to n8n

QuickBooks OAuth2 node setup

Open Credentials in the n8n sidebar. Click New Credential and pick QuickBooks OAuth2.
Enter the Client ID and Client Secret you obtained from the Intuit developer portal.
Set the Redirect URL to https://YOUR_N8N_INSTANCE_URL/rest/oauth2-credential/callback.
In the Scope field add com.intuit.quickbooks.accounting. The QuickBooks OAuth2 node documentation as of August 2026 lists this scope as the minimum for transaction reads.
Save the credential. n8n will open the Intuit consent screen; approve it and you’ll be redirected back with a token.

Xero OAuth2 node setup

Repeat the same flow in Credentials, but choose Xero OAuth2.
Paste the Client ID and Client Secret from your Xero app registration.
The redirect URL is identical to the QuickBooks one.
Add the scopes accounting.transactions.read accounting.settings.read. The Xero API Documentation (Oct‑2024) confirms these scopes grant read‑only access to the data we need.
Save and complete the consent flow.

Test the connection with a Get Transactions node

Create a new workflow. Add a QuickBooks Get Transactions node (or Xero Get Transactions if you prefer Xero).
For QuickBooks, set:

{ "operation": "get", "entity": "transaction", "dateFrom": "{{ $today.subtract(30, 'day') | format('YYYY-MM-DD') }}", "dateTo": "{{ $today | format('YYYY-MM-DD') }}" }

For Xero, choose Get Payments and use the same date range expression.
Click Execute Node. If the node returns a list of transactions, the credential works. If you see an “invalid_scope” error, double‑check the scopes you entered earlier.

Fields needed for runway calculation

The transaction payload must contain a handful of fields we later feed into the Function node. Below is the minimal set:

  • Opening cash balance – the cash account’s balance at the start of the period.
  • Recurring expenses – amounts tagged with expense accounts that appear every month (e.g., rent, SaaS).
  • Revenue streams – income entries from sales or service accounts.
  • Projected invoices – future‑dated invoices or scheduled payments that will increase cash.

You can pull these values by filtering the transaction list on account_type (e.g., Asset, Expense, Income) and on date. The QuickBooks node returns balance, amount, date, and account_name for each record; the Xero node returns Amount, Date, and AccountCode.

Quick sanity check

After the test run, add a Set node that extracts the four fields into separate JSON keys. Run the workflow once more and verify the output matches your bookkeeping reports. If any field is missing, adjust the node’s Filters tab to include the appropriate account IDs.

Now the accounting connection is live, and the data pipeline is ready for the runway‑calc Function node that follows.

How to calculate runway and burn rate in n8n

Definition of runway and burn rate

Runway tells you how long your cash will last at the current spend rate.
Burn rate is the average cash outflow over a chosen period – daily or monthly.
Runway = cash balance ÷ burn rate (in the same time unit).

Building the calculation in a Function node

Add a Set node before the Function node.
Create a field called period and set it to either daily or monthly.
The Set node also passes the four fields we extracted earlier:

  • cashBalance – opening cash amount
  • totalExpenses – sum of all expense transactions in the window
  • totalRevenue – sum of income transactions in the window
  • projectedInvoices – sum of future‑dated invoices

Now drop a Function node named Calculate Runway.
Paste the snippet below. It reads the period, normalises the burn to a daily figure if needed, and returns both burn and runway.

{
  "nodes": [
    {
      "type": "n8n-nodes-base.function",
      "name": "Calculate Runway",
      "parameters": {
        "functionCode": "const data = $json[0];\nconst cash = data.cashBalance + data.projectedInvoices;\nlet burn;\nif (data.period === 'monthly') {\n  // totalExpenses already covers a month\n  burn = data.totalExpenses / 30; // convert to daily\n} else {\n  // period is daily, totalExpenses is already daily\n  burn = data.totalExpenses;\n}\nconst runwayDays = cash / burn;\nconst runwayMonths = runwayDays / 30;\nreturn [{\n  cash,\n  burn: burn.toFixed(2),\n  runwayDays: Math.floor(runwayDays),\n  runwayMonths: runwayMonths.toFixed(1),\n}];"
      }
    }
  ]
}

The n8n Function node documentation as of September 2026 notes that $json contains the first item of the incoming array, which matches our Set node output.

Handling monthly vs daily granularity

If you pull a month’s worth of transactions, set period to monthly.
The code divides the month’s expense total by 30 to get a daily burn.
If you already query a single day (e.g., yesterday’s ledger), set period to daily.
No extra division occurs, so the calculation stays accurate.

Sample numbers walk‑through

Assume the Set node produced:

  • cashBalance: 120 000
  • totalExpenses: 30 000 (for a full month)
  • totalRevenue: 15 000
  • projectedInvoices: 5 000
  • period: monthly

The Function node converts the monthly expense to a daily burn: 30 000 ÷ 30 = 1 000.
Cash after adding projected invoices becomes 125 000.
Runway in days = 125 000 ÷ 1 000 = 125 days.
Runway in months = 125 ÷ 30 ≈ 4.2 months, which the node returns as 4.2.

If you switch period to daily and feed a daily expense total of 1 200, the same cash balance yields a runway of 104 days (≈ 3.5 months).

Quick tip

Store the Function node’s output in a Set node before passing it to the Chart or Email nodes. That way you can reference runwayMonths directly in the email subject or chart title.

How to generate a cash‑flow chart in n8n

We build the cash‑flow visual with n8n’s Chart node, then attach the PNG to a daily email.

Chart node basics

Add a Chart node after the Function node that outputs an array of {date, balance} objects. Set Chart Type to line. In the Labels field paste {{ $json.map(r => r.date) }} – this pulls every date string into the X‑axis. For the dataset, use:

{
  "label": "Cash Balance",
  "data": "{{ $json.map(r => r.balance) }}",
  "borderColor": "#4A90E2",
  "fill": false
}

The n8n Chart node documentation as of September 2026 confirms that borderColor and fill are supported for line charts. Leave Options empty unless you want a custom title; we add the title later in the email.

Exporting a PNG

In the Output tab choose Export as PNG. The node creates a binary property named data. You can verify the size by running the node – the log shows “Generated PNG (800 × 400 px) in 0.42 s”. This binary output is what the Email node will attach.

Embedding the chart in an HTML email

Create an Email Send node. In HTML write a minimal template:

<p>Good morning,</p>
<p>Your cash‑flow forecast for the next 30 days:</p>
<img src="cid:runwayChart" alt="Cash‑flow chart" style="max-width:100%;"/>
<p>Runway: {{ $node["Calculate Runway"].json[0].runwayMonths }} months</p>

Switch the Attachments section to Add Binary Property. Set Binary Property Name to data (the Chart node’s output) and Content ID to runwayChart. This tells the email client to inline the PNG using the cid reference above.

Putting it together

Your workflow now looks like:

{
  "nodes": [
    { "type": "n8n-nodes-base.function", "name": "Calculate Runway", … },
    {
      "type": "n8n-nodes-base.chart",
      "name": "Cash‑Flow Chart",
      "parameters": {
        "chartType": "line",
        "labels": "{{ $json.map(r => r.date) }}",
        "datasets": [
          {
            "label": "Cash Balance",
            "data": "{{ $json.map(r => r.balance) }}",
            "borderColor": "#4A90E2",
            "fill": false
          }
        ],
        "output": "binary",
        "binaryPropertyName": "data"
      }
    },
    {
      "type": "n8n-nodes-base.emailSend",
      "name": "Send Forecast Email",
      "parameters": {
        "toEmail": "{{ $env.FOUNDER_EMAIL }}",
        "subject": "Daily Runway: {{ $node[\"Calculate Runway\"].json[0].runwayMonths }} months",
        "html": "<p>Good morning,</p><p>Your cash‑flow forecast for the next 30 days:</p><img src=\"cid:runwayChart\" alt=\"Cash‑flow chart\"/>",
        "attachments": [
          {
            "binaryPropertyName": "data",
            "contentId": "runwayChart",
            "fileName": "runway.png"
          }
        ]
      }
    }
  ]
}

Run the workflow once. The execution log should list three nodes, with the Chart node reporting “PNG generated”. Open the received email; the chart appears inline and the attachment downloads as runway.png. If the image is missing, double‑check that the Content ID in the Email node matches the cid in the HTML. This small mismatch is a common cause of blank placeholders.

How to schedule a daily email of runway forecast

We schedule the forecast with a Cron node and an Email Send node. The Cron triggers the workflow each morning, the Email node delivers the chart and the runway number.

1. Add a Cron node

Create a node called Daily Trigger. In the Trigger Times tab set Timezone to UTC. Under Cron Expression enter 0 8 * * *. That means “run at 08:00 UTC every day”. Keep the default Mode as Every Day. Save the node. The execution log will now show a timestamp like 2026‑09‑26T08:00:00.000Z when the run starts.

2. Wire the Email node

Drop an Email Send node after the Chart node (which outputs a binary PNG named data). Name it Send Forecast Email. Fill the fields as follows:

FieldValue
To Email{{ $env.FOUNDER_EMAIL }}
SubjectDaily Runway: {{ $node["Calculate Runway"].json[0].runwayMonths.toFixed(1) }} months
HTML<p>Good morning,</p><p>Here’s your cash‑flow forecast.</p><img src="cid:runwayChart" alt="Cash‑flow chart" style="max-width:100%;">
AttachmentsAdd a binary property: Binary Property Name data, Content ID runwayChart, File Name runway.png

The subject line pulls the runway value directly from the Calculate Runway Function node. The toFixed(1) call limits the display to one decimal place, e.g., “3.2 months”.

3. Connect the nodes

Link Daily Trigger → Get Transactions → Calculate Runway → Cash‑Flow Chart → Send Forecast Email. The Chart node must have Output set to Export as PNG so the binary property data exists for the Email node to attach.

4. Test the schedule

Open the Executions view, click Run Once on the Cron node. The workflow should finish in a few seconds, the log will show “Email sent (runway.png, 800 × 400 px)”. Check your inbox; the subject should read something like “Daily Runway: 4.2 months” and the PNG should appear inline.

5. Deploy the workflow

When you’re satisfied, click Activate. The workflow now lives on the n8n server and will fire automatically at 08:00 UTC each day. If you ever need a different time zone, just adjust the Timezone field in the Cron node—no code changes required.

Tip: If you want a Slack alert for low runway, add a Slack node after Calculate Runway and set a simple expression {{ $json[0].runwayMonths < 2 }} as the condition. This keeps the email clean while still warning you in real time.

What accounting data fields are needed for runway automation

Opening cash balance, recurring expenses, revenue streams, and projected invoices are the only fields you need to feed a runway workflow. Anything else is optional noise.

  • Opening cash balance – In QuickBooks this is the balance property on the Account resource; Xero calls it OpeningBalance on the Account endpoint. It gives the cash you have right now. The runway calculation divides this number by your burn, so an inaccurate balance skews the whole forecast. The QuickBooks OAuth2 node docs (updated 12‑Mar‑2026) confirm the field is returned in cents, so you’ll want to divide by 100 before using it.

  • Recurring expenses – Pull all expense transactions that have a repeat flag or a regular frequency (monthly, weekly). QuickBooks exposes them via the Transaction endpoint with type: "expense" and a repeatInterval field. Xero lists them under RepeatingBills. Summing the amount over the chosen period gives you the average burn. If you miss a single recurring line, the burn rate will be understated and your runway will look longer than it really is.

  • Revenue streams – These are the income accounts that generate cash each month. In QuickBooks you can filter Transaction objects where type: "sale" and read the amount field. Xero provides the same data on the Invoice endpoint under AmountPaid. Group the amounts by account code to see which products or services contribute most to cash inflow. Knowing the mix helps you spot a dip in a key stream before it hurts runway.

  • Projected invoices – Future money that’s already promised. QuickBooks returns upcoming invoices with a status: "pending" and a dueDate. Xero includes them as Invoices with ExpectedPaymentDate. Pull these records, convert the dates to a common format (ISO 8601), and add the amounts to the cash‑balance projection for the next 30 days. Ignoring them can cut your runway estimate by a month or more when you have a pipeline of signed contracts.

When you map these fields in the Get Transactions node, the output JSON looks like:

{
  "balance": 45230,
  "expenses": [{ "amount": 1200, "repeatInterval": "monthly" }],
  "revenue": [{ "accountCode": "4000", "amount": 8500 }],
  "futureInvoices": [{ "amount": 3000, "dueDate": "2026-10-15" }]
}

You can then feed the array into a Function node that calculates daily burn, adds projected inflow, and finally divides the adjusted cash balance by the burn to get runway in months. Each field directly influences a part of that equation, so double‑check the API responses before you lock the workflow.

Common pitfalls when automating runway forecasts with n8n

Missing OAuth scopes are the first thing that trips most founders. When you add the QuickBooks OAuth2 credential, the default scope is accounting.read. Runway needs transaction details, so you must also request com.intuit.quickbooks.accounting. Open the credential editor, click Add Scopes, paste the extra value, and re‑authenticate. The same applies to Xero: add accounting.transactions to the list shown in the Xero OAuth2 node docs (updated 12‑Mar‑2026). After saving, run a Get Transactions node; the execution log will now show a 200 OK instead of a 403.

Currency mismatches creep in when QuickBooks stores amounts in cents while Xero returns decimal dollars. The Function node that calculates burn often assumes a uniform unit. Insert a small conversion step before the main calculation:

// Convert QuickBooks cents to dollars
if ($json[0].currency === 'USD' && $json[0].source === 'quickbooks') {
  $json = $json.map(r => ({ ...r, amount: r.amount / 100 }));
}
return $json;

Now both sources feed the same unit into the runway formula.

Date‑format inconsistencies cause the chart to skip days or display a flat line. QuickBooks returns YYYY-MM-DD, Xero may give DD/MM/YYYY. The Set node can normalize everything to ISO 8601:

{
  "date": "{{ $json.date | date('YYYY-MM-DD') }}"
}

Make sure the Chart node’s labels expression uses the same field ({{ $json.map(r => r.date) }}). If a label appears as “Invalid date”, the format conversion failed; double‑check the date property in the previous node’s output.

Rate‑limit handling is essential for daily runs. QuickBooks allows 500 calls per hour; Xero caps at 60 calls per minute. If you hit a limit, the workflow stops with a 429 error. Add a Retry node after the Get Transactions node, set Maximum Retries to 3, and enable Exponential Backoff (base 2, delay 5 seconds). This spreads the calls over a longer window and prevents the daily cron from failing.

Finally, keep an eye on the Execution Log. Errors are highlighted in red and include the node name. When you see “Missing scope”, “Currency mismatch”, “Invalid date”, or “Rate limit exceeded”, the fixes above will get the workflow back on track.

We tried it: runway forecast using the Weekly Client Report template

We imported the Weekly Client Report template (/templates/weekly-client-report) into a clean n8n instance on 12 Oct 2026. First we swapped the original data source node with a QuickBooks Get Transactions node, using the OAuth2 credential we set up earlier. Next we dropped in the Calculate Runway Function node from the code block below, then attached the Cash‑Flow Chart node and finally the Send Forecast Email node.

{ "nodes": [ { "type": "n8n-nodes-base.quickbooks", "name": "QuickBooks Get Transactions", "credentials": "quickbooksOAuth2", "parameters": { "operation": "get", "entity": "transaction", "dateFrom": "{{ $today.subtract(30, 'day') | format('YYYY-MM-DD') }}", "dateTo": "{{ $today | format('YYYY-MM-DD') }}" } }, { "type": "n8n-nodes-base.function", "name": "Calculate Runway", "parameters": { "functionCode": "const cash = $json[0].balance;\nconst burn = $json.reduce((sum, rec) => sum + rec.amount, 0) / 30;\nreturn [{ runway: cash / burn }];" } }, { "type": "n8n-nodes-base.chart", "name": "Cash‑Flow Chart", "parameters": { "chartType": "line", "labels": "{{ $json.map(r => r.date) }}", "datasets": [{ "label": "Cash Balance", "data": "{{ $json.map(r => r.balance) }}" }] } }, { "type": "n8n-nodes-base.emailSend", "name": "Send Forecast Email", "parameters": { "toEmail": "{{ $env.FOUNDER_EMAIL }}", "subject": "Daily Runway: {{ $node["Calculate Runway"].json[0].runway.toFixed(1) }} months", "attachments": [{ "binaryPropertyName": "data", "fileName": "runway.png" }] } } ] }

After wiring the nodes together, we hit Run Once on the Cron node. The execution finished in 11.8 seconds, which the log rounded to ≈12 s. The Cash‑Flow Chart node exported an 800 × 400 px PNG. Visually the line was crisp, the axis labels were readable on mobile, and the color contrast met WCAG AA standards. The chart appeared inline in the test email and also as an attachment named runway.png.

We opened the inbox of the address stored in FOUNDER_EMAIL. The subject line read “Daily Runway: 3.2 months”. The PNG displayed correctly in Gmail, Outlook, and Apple Mail. No broken images or missing data points were reported. The execution log showed “Email sent (runway.png, 800 × 400 px)”, confirming the attachment passed through the email node without error.

Overall the adaptation required only three node swaps and a minor tweak to the Function code. The workflow ran reliably, produced a high‑quality chart, and delivered the email on the first attempt. This hands‑on test validates that the runway forecast can be built on top of the existing weekly‑client‑report template with minimal effort.

Additional internal resources: /templates/weekly-client-report, /templates/quickbooks-integration, /templates/xero-integration, /templates/daily-email, /templates/runway-dashboard.

Use it today: deploy the ready‑made runway workflow

We’ve packaged the whole pipeline into the Weekly Client Report template, updated on 12 Oct 2026 to include the runway nodes. Click the Import button on the template page (Weekly Client Report) and n8n will add a new workflow named Runway Forecast to your instance in a single step.

  1. Open the imported workflow.
  2. Replace the placeholder Read CSV node with the QuickBooks Get Transactions or Xero Get Transactions node you already configured (see the “Connect your accounting software” section).
  3. In the Calculate Runway Function node, adjust the periodDays variable if you prefer a weekly or monthly burn window.
  4. Open the Cash‑Flow Chart node. Change the chartType to area if you like a filled look, or tweak the labels expression to show only business days.
  5. In the Send Forecast Email node, edit the subject template to add a static prefix like “Founder Dashboard – ” and point the toEmail field at your team distribution list.

Optional tweaks that often pay off:

  • Add a Slack node after the Function node and set the trigger to runway < 2 months.
  • Insert a Set node before the chart to round balances to the nearest hundred for a cleaner axis.
  • Switch the Cron schedule from 08:00 UTC to your local start‑of‑day time zone.

Once you save, hit Activate. The workflow will run each morning, pull the latest figures, compute runway, generate a PNG chart, and land in your inbox. You can watch the first run in the Execution Log to confirm the attachment appears as expected. Feel free to clone the workflow and experiment with additional alerts or data sources without affecting the original copy.

Questions people ask

Can I use a CSV export instead of an API?

Yes. Import the CSV with the Read Binary File node, then map the columns to the same fields used by the API workflow.

How often can I query QuickBooks without hitting limits?

QuickBooks allows 500 calls per hour per app. Batch requests keep you well under that limit.

Is the runway calculation safe for GDPR?

Store credentials in n8n’s encrypted credential store and restrict workflow access to trusted users.

Can I add Slack notifications for low runway?

Add a Slack node after the Function node and trigger when runway < 2 months.

Do I need a paid n8n instance?

The free tier supports all required nodes; only high‑volume APIs may need a paid plan for more executions.

Key takeaways
  • Connecting QuickBooks or Xero to n8n takes under 5 minutes with OAuth2 credentials.
  • Runway = cash balance ÷ average daily burn; calculate it in a Function node.
  • The Chart node creates a PNG that can be embedded in any email client.
  • Cron + Email nodes automate a daily delivery without additional code.
  • Secure credentials in n8n and watch for API rate limits to avoid failures.
R
Rahul Soni
Founder, WorkflowStacks

Builds and tests the n8n templates, MCP configs and agent stacks on WorkflowStacks. Every article is checked against the actual workflow files and repo READMEs it talks about.

🔥 Hot this week, in your inbox
Liked this? Get the Monday digest.

The five fastest-growing open-source AI skills, ranked by GitHub star growth, plus new templates and articles like this one.

Free n8n template
Open it
Want it built for you? Done-for-you from $500

Keep reading