How it works
- Step 1Export from your online banking — Use the bank's native CSV download. UK retail banks (Lloyds, Barclays, NatWest, HSBC) put it under
Statements → Download → CSV. US banks (Chase, Wells Fargo) call itActivity → Download → Comma-separated values. Note your bank's row in the shapes table below — column order, header presence, and date format all matter. - Step 2Fork the workflow into your drafts — Click
Fork to my drafts. The fork endpoint copies this static 6-node blueprint into a private workflow you own, auto-wires the chain out→in, and snapshots it as v1. Forking is free-tier and needs no credentials — every node is a pure in-browser CSV tool. - Step 3Adjust Step 1 for your specific bank — Open the
csv-cleanernode. SetskipRowsto strip the summary preamble: HSBC ≈ 8, Lloyds ≈ 5, Barclays / Chase / Wells Fargo = 0. TogglenormalizeSmartQuoteson if the export came via a copy-paste, and pick the output line ending (crlffor QuickBooks). - Step 4Confirm the regex passes run as regex — Steps 2–4 ship
useRegex: truein the blueprint. Verify theuseRegextoggle is on in eachcsv-find-replacenode before running — without it the patterns match literally and the day-of-week / currency / bracket-negative cleanup silently does nothing. Test on a 20-row sample first. - Step 5Pick your target tool in Step 6 — Step 6's
renamesJSON decides which accounting tool you're feeding. Paste the QBO 3-col, QBO 4-col, Xero, FreeAgent, or Sage block from the cookbook. The header names are exact and case-sensitive —transaction dateis notTransaction Date. - Step 6Run, review the trace, then import — Drop your CSV on the first node and Run. The run is recorded in the workflow's run history with a per-node trace (status, duration, output size) you can re-open. Download the final CSV, then import: QuickBooks → Banking → Upload from file (350 KB cap); Xero → Bank accounts → Manage → Import a statement; FreeAgent → Banking → Upload Statement (5 MB cap).
The real node chain (forked graph)
Exactly what the fork places on the canvas, in order, with the blueprint config and the port wiring. All six nodes are csv-category, free-tier, browser-local; the fork auto-wires each csv → csv edge.
| # | Node (tool slug) | What it does in this chain | Blueprint config | Ports (in → out) |
|---|---|---|---|---|
| 1 | `csv-cleaner` | Trim, repair rows, drop blanks; preamble/quote/encoding handling via node config | trimWhitespace:true, removeEmptyRows:true, repairRows:true, normalizeSmartQuotes:true, skipRows:0 | csv → csv |
| 2 | `csv-find-replace` | Strip day-of-week date suffix (… TUE) | find:\s+(MON|TUE|WED|THU|FRI|SAT|SUN)$, replace:'', useRegex:true | csv → csv |
| 3 | `csv-find-replace` | Strip currency symbols from amounts | find:[£$€¥], replace:'', useRegex:true | csv → csv |
| 4 | `csv-find-replace` | Convert (30.00) → -30.00 | find:\(([\d.,]+)\), replace:-$1, useRegex:true | csv → csv |
| 5 | `csv-deduplicator` | Collapse pending-vs-posted duplicate rows | columns:Date,Amount,Description, strategy:last | csv → csv |
| 6 | `csv-header-rename` | Rename headers to the target tool's exact shape | renames:{Date:transaction date, Description:memo, Amount:amount} | csv → csv |
Bank CSV shapes — what each bank writes
Column order, header presence, date format, quirks. Header row? matters most: Wells Fargo omits it entirely, so set the headers manually in Step 6.
| Bank | Columns (in order) | Header row? | Date format | Negative amounts | Quirks |
|---|---|---|---|---|---|
| Chase (US, checking) | Details, Posting Date, Description, Amount, Type, Balance, Check or Slip # | Yes | MM/DD/YYYY | -30.00 | Caps at ~24 months and 1,000 rows per export. |
| Wells Fargo (US) | Date, Amount, *, *, Description (5 columns, two blank) | **No** | MM/DD/YYYY | -30.00 | Header row **omitted** — first row is the first transaction. Add headers via Step 6 renames by index. |
| HSBC (UK) | Date, Type, Description, Paid out, Paid in, Balance (after summary) | Yes — preceded by 5–10 summary lines | DD MMM YYYY | Separate Paid out / Paid in | Top of file is unstructured text. Set skipRows: 8 on the csv-cleaner node. |
| Lloyds (UK) | Transaction Date, Transaction Type, Sort Code, Account Number, Transaction Description, Debit Amount, Credit Amount, Balance | Yes | DD/MM/YYYY | Separate Debit / Credit | Sort Code + Account Number repeat every row. Either Debit or Credit is empty per row. |
| Monzo (personal) | Long — Transaction ID, Date, Time, Type, Name, Emoji, Category, Amount, Currency, … | Yes | DD/MM/YYYY | -30.00 | Includes Pot transfers + FX lines. Add a `csv-column-filter` step for accounting-only rows. |
| Revolut | Type, Product, Started Date, Completed Date, Description, Amount, Fee, Currency, State, Balance | Yes | YYYY-MM-DD HH:MM:SS | -30.00 | Filter State = COMPLETED first — pending/reverted rows create phantom transactions. |
Accounting-tool format requirements
Verbatim error strings, file-size limits, exact column shapes. Step 6's renames decides the target shape; the size caps are the tool's, not the workflow's.
| Tool | Required columns | Date format | Negative format | File size | Verbatim error if wrong |
|---|---|---|---|---|---|
| QuickBooks Online (3-col) | Date, Description, Amount → renamed to transaction date, memo, amount | Configured at mapping | -30.00 only — brackets rejected | **350 KB** | Your file does not contain the three required columns: transaction date, memo and amount |
| QuickBooks Online (4-col) | Date, Description, Credit, Debit | Configured at mapping | Positive in respective columns | **350 KB** | We can't upload this .CSV file because some of the columns aren't mapped correctly |
| Xero (UK / AU / NZ) | Date, Amount minimum | DD/MM/YYYY | Either -30.00 OR (30.00) | Not documented | Some lines in your file aren't formatted correctly |
| FreeAgent | Date, Amount, Description | DD/MM/YYYY | -30.00 | 5 MB | Sorry, we couldn't read your bank statement |
| Sage 50 | Date, Reference, Description, Net amount, Tax amount, Total | DD/MM/YYYY | -30.00 | Not documented | The file you have selected is not in the correct format |
Cookbook
Step 6's renames JSON for the most common accounting-tool targets, plus the two upstream tweaks that matter most. Header names are exact and case-sensitive — paste them verbatim.
QuickBooks Online — 3-column format
ExampleQBO's required headers are lowercase: transaction date, memo, amount. The exact wording matters — this is the only block that clears the 'three required columns' error.
{
"Date": "transaction date",
"Description": "memo",
"Amount": "amount"
}QuickBooks Online — 4-column format
ExampleUse when your bank splits debit/credit into separate columns (Lloyds Debit/Credit, HSBC Paid out / Paid in). QBO maps four columns max.
{
"Date": "transaction date",
"Description": "memo",
"Debit Amount": "debit",
"Credit Amount": "credit"
}Xero — UK / AU / NZ
ExampleXero requires only Date and Amount; Payee aids reconciliation. Xero accepts both -30.00 and (30.00), so Step 4 is optional for Xero-only output.
{
"Date": "Date",
"Description": "Payee",
"Amount": "Amount"
}FreeAgent
ExampleFreeAgent uses title-case column names and a generous 5 MB cap, so date-range splitting is rarely needed.
{
"Date": "Date",
"Description": "Description",
"Amount": "Amount"
}HSBC preamble — Step 1 node config
ExampleHSBC and Lloyds prepend a multi-line summary above the real header. Set this on the csv-cleaner node so the header row lands at row 1. Tune the number to your bank's actual preamble depth.
{
"skipRows": 8,
"trimWhitespace": true,
"normalizeSmartQuotes": true,
"removeEmptyRows": true
}Edge cases and verbatim errors
Regex passes match literally — cleanup does nothing
Config errorThe three csv-find-replace nodes only treat find as a regex when the node's useRegex toggle is on. The blueprint ships useRegex: true, but if a node is edited or re-added without it, patterns like [£$€¥] and \(([\d.,]+)\) are matched as literal strings and quietly replace nothing. Symptom: amounts still carry symbols/brackets after a clean run. Fix: confirm useRegex is on in every find-replace node.
Dedupe keys on the first column only
Runtime limitationAlthough the node accepts columns: Date,Amount,Description, the chained runner keys on the **first** match column and keeps the **first** occurrence regardless of the strategy: last setting. With Date first, two different transactions on the same date can collapse. Fix: put the most-unique column first (a Transaction ID or Time column if your bank emits one), or run `csv-deduplicator` standalone where multi-column matching applies.
`We can't upload this .CSV file because some of the columns aren't mapped correctly`
QuickBooks OnlineQBO accepts only 3-col or 4-col files. Causes: more than 4 columns, a header name in the wrong case, or invalid characters (curly quotes, emoji, en-dashes). Enable normalizeSmartQuotes on Step 1, drop extra columns with `csv-column-filter`, and use the exact Step 6 rename.
`Your file does not contain the three required columns: transaction date, memo and amount`
QuickBooks OnlineQBO is case-sensitive: transaction date (lowercase, two words), memo, amount. The cookbook's 3-col rename produces this exact wording — Transaction Date or Memo will still fail.
QuickBooks 350 KB cap silently truncates
Silent truncationFiles over 350 KB upload 'successfully' but only the first ~350 KB of rows reach the For Review queue. The workflow can't raise QBO's cap. Split the export by date range before importing, or target Xero / FreeAgent (no 350 KB limit).
`Some lines in your file aren't formatted correctly`
XeroXero imports the valid rows and lists the failed row numbers — almost always a date-format/locale mismatch. Check your Xero org's region, then re-export with the matching date order; the workflow doesn't reorder date components.
Empty file or all rows blank after cleaning
failIf the input is empty or removeEmptyRows plus a too-aggressive skipRows strips everything, downstream nodes receive a header-only or empty CSV and the run produces a 0-row output. The run trace shows each node's row count in its summary — check Step 1's output before blaming Step 6.
Wells Fargo export with no header row
Misread by every generic cleanerWells Fargo omits the header row, so the first transaction is treated as headers. `csv-header-rename` can target columns by index, but the cleaner steps assume a header — prepend a header line (Date,Amount,col3,col4,Description) before forking, or accept the first transaction being consumed as a header.
Mac-saved CSV with bare `\r` line endings
QuickBooks OnlineExcel for Mac writes lone \r; QBO expects \r\n and reads the whole file as one row. Set the csv-cleaner node's output line ending to crlf so the export is Windows/QuickBooks-safe.
Forking requires sign-in; running needs no upgrade
Auth requiredThe fork endpoint returns 401 unauthorized if you're not signed in — anyone authenticated can fork any published blueprint. Once forked, all six CSV nodes are free-tier, so the tier precheck passes and no upgrade prompt appears when you run.
Frequently asked questions
What exactly does the Fork button do?
It POSTs to the from-blueprint endpoint, which reads this static 6-node blueprint, places each node left-to-right on a canvas, auto-wires every consecutive csv → csv edge, and creates a **private** workflow row you own with the default config already applied. It also snapshots that graph as version 1 and writes a forked audit event tagged with this blueprint's slug. You land in the editor with the chain pre-built — you just drop your CSV and adjust per-bank settings.
Does my bank statement get uploaded to a server?
No. Every node in this chain is a pure CSV tool that runs in your browser — csv-cleaner, csv-find-replace, csv-deduplicator, and csv-header-rename all read the dropped file's text client-side and process it locally. The server only ever stores the workflow graph (the node list and config), never your statement data. No external credentials are involved because none of these tools call an outside service.
Do I need a paid plan to fork or run this workflow?
No. None of the six CSV tools declare a minimum tier, so they all default to free. The tier precheck that gates a run computes the strictest minTier across the graph and finds 'free', so it passes for everyone. You do need to be signed in to fork (the fork endpoint requires authentication), but there's no upgrade gate to run it.
Can I schedule this to run automatically every month?
The platform supports cron scheduling — a Cloudflare Cron Trigger periodically scans workflows that have a schedule_cron, decides which are due since their last fire, and enqueues a run. But this blueprint forks with scheduleCron: null, i.e. as a manual/drag-a-file workflow. Bank cleaning is inherently a 'drop the new export' task, so there's nothing to fetch on a timer. If you want it scheduled, set a cron on your forked copy and wire an upstream fetch step yourself.
Why are the find-and-replace steps still leaving currency symbols in?
Almost always because the useRegex toggle got turned off on that node. The blueprint ships all three find-replace nodes with useRegex: true, which is what makes [£$€¥] and \(([\d.,]+)\) behave as patterns. Without it, the runner escapes the pattern and matches it as a literal string, so nothing changes. Re-enable useRegex on each find-replace node and re-run.
Is `(30.00)` the same as `-30.00` for accounting imports?
It depends on the tool. Xero accepts both. QuickBooks Online accepts only the minus-sign form — brackets cause a silent rejection. Older Sage versions prefer brackets; FreeAgent wants signed only. Step 4 rewrites brackets to minus-sign form because that's the safest universal output across all of them.
How does the dedupe step decide which duplicate to keep?
The csv-deduplicator node exposes columns and a keep-first/keep-last strategy. Be aware that the chained runner keys on the first column you list and keeps the first occurrence it sees, rather than honoring keep-last or matching across all listed columns. For exact same-day same-amount transactions you want to preserve, put a unique column (Transaction ID, Time) first, or do the dedupe in the standalone `csv-deduplicator` where multi-column matching is fully applied.
Why does QuickBooks say my file isn't mapped correctly even after cleaning?
QBO accepts only 3-column (Date, Description, Amount) or 4-column (Date, Description, Credit, Debit) files. The error fires when the file has more than 4 columns, a header is misspelled or mis-cased, or it contains 'invalid characters' (emoji, en-dashes, curly quotes). Trim extra columns with `csv-column-filter`, enable normalizeSmartQuotes on Step 1, and use the exact Step 6 rename.
How do I handle HSBC's summary lines at the top of the file?
Open the csv-cleaner node and set skipRows to the number of preamble lines before the real header — HSBC is typically around 8, Lloyds around 5. The standalone csv-cleaner honors skipRows directly; if you're cleaning preamble inside the chained run and it isn't taking effect, run csv-cleaner standalone first to strip the preamble, then feed the result into the workflow.
Can I reuse this for a Revolut or Monzo export?
Yes, with one extra step. Add a `csv-column-filter` node after Step 1 to keep only the rows you want — for Revolut, State = COMPLETED (its State column also includes PENDING, REVERTED, DECLINED, which would otherwise import as phantom transactions); for Monzo, filter out Pot transfers and FX lines. Then continue through the normal chain.
Where can I see whether a run actually succeeded?
Each run is recorded in the workflow's run history with a per-node trace — node status, duration, output size, and a one-line summary (csv-cleaner reports inputRows → outputRows, find-replace reports replacement count, dedupe reports duplicates removed). The runs endpoint returns the last 50 runs newest-first, and fork/run actions are also logged as audit events, so you can confirm exactly which step changed what.
What's the difference between this workflow and the other CSV-cleaning workflows?
This one is tuned for the specific failure modes of bank exports going into accounting tools. For a generic same-file dedupe see `dedupe-excel-csv-workflow`; for e-commerce exports see `clean-shopify-csv-workflow` and `clean-amazon-seller-csv-workflow`; for merging and deduping lead lists see `clean-real-estate-leads-workflow`. They share the same node toolkit but pre-wire different chains and configs.
Local-first by design
This workflow executes entirely on your jadapps-runner. API keys, database credentials, and OAuth tokens are stored in an AES-GCM-encrypted vault on your device — they are never uploaded to JAD Apps' servers. The server only stores the workflow graph (the recipe), not the secrets.