Created
December 3, 2025 13:02
-
-
Save alex-phillips/deb74af8832c05fc3239e48ccf6d7630 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "Transactions to YNAB", | |
| "nodes": [ | |
| { | |
| "parameters": { | |
| "mode": "runOnceForEachItem", | |
| "jsCode": "const body = $json[\"text\"]\n\nconst amount = body.match(/\\$(\\d+\\.\\d+)/)[1]\nconst payee = body.match(/Where:\\s+(.+?)[\\n|$]/)[1]\n\nreturn {\n data: {\n bank: \"BoA Credit\",\n amount,\n payee, \n }\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 272, | |
| 560 | |
| ], | |
| "id": "0494e970-35ec-40d7-9b5e-c9a186cb2fbc", | |
| "name": "Parse BoA Trx" | |
| }, | |
| { | |
| "parameters": { | |
| "mode": "runOnceForEachItem", | |
| "jsCode": "const body = $json[\"text\"]\n\nconst parsed = body.match(/these\\s+large\\s+purchase\\s+notifications\\s+online\\.\\s+([^\\n]+)\\s+\\$(\\d+\\.\\d+)/m)\nconst payee = parsed[1]\nconst amount = parsed[2]\n\nreturn {\n data: {\n bank: \"Amex Blue\",\n amount,\n payee,\n }\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 272, | |
| 752 | |
| ], | |
| "id": "d6947a69-0527-4a30-a7c1-dac53d162b33", | |
| "name": "Parse Amex Trx" | |
| }, | |
| { | |
| "parameters": { | |
| "url": "https://api.ynab.com/v1/budgets/YNAB_BUDGET_ID/payees", | |
| "authentication": "predefinedCredentialType", | |
| "nodeCredentialType": "httpBearerAuth", | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.3, | |
| "position": [ | |
| 272, | |
| 176 | |
| ], | |
| "id": "2616aa6c-08c0-4132-869d-cf60cea1ffb9", | |
| "name": "YNAB Payees", | |
| "executeOnce": true | |
| }, | |
| { | |
| "parameters": { | |
| "url": "https://api.ynab.com/v1/budgets/YNAB_BUDGET_ID/accounts", | |
| "authentication": "predefinedCredentialType", | |
| "nodeCredentialType": "httpBearerAuth", | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.3, | |
| "position": [ | |
| 272, | |
| 368 | |
| ], | |
| "id": "9305e209-eb83-45ca-86e2-61fecd39cd4b", | |
| "name": "YNAB Accounts", | |
| "executeOnce": true | |
| }, | |
| { | |
| "parameters": { | |
| "numberInputs": 3 | |
| }, | |
| "type": "n8n-nodes-base.merge", | |
| "typeVersion": 3.2, | |
| "position": [ | |
| 496, | |
| 640 | |
| ], | |
| "id": "5d003e38-dc93-4001-87ff-cff45903a7fd", | |
| "name": "Merge" | |
| }, | |
| { | |
| "parameters": { | |
| "rules": { | |
| "values": [ | |
| { | |
| "conditions": { | |
| "options": { | |
| "caseSensitive": true, | |
| "leftValue": "", | |
| "typeValidation": "strict", | |
| "version": 2 | |
| }, | |
| "conditions": [ | |
| { | |
| "id": "3d7c2894-cb6b-41d0-b496-4f0746ec1aea", | |
| "leftValue": "={{ $json.subject }}", | |
| "rightValue": "BoA Alert Subject", | |
| "operator": { | |
| "type": "string", | |
| "operation": "contains" | |
| } | |
| } | |
| ], | |
| "combinator": "and" | |
| }, | |
| "renameOutput": true, | |
| "outputKey": "BoA" | |
| }, | |
| { | |
| "conditions": { | |
| "options": { | |
| "caseSensitive": true, | |
| "leftValue": "", | |
| "typeValidation": "strict", | |
| "version": 2 | |
| }, | |
| "conditions": [ | |
| { | |
| "id": "896bab85-f204-414b-a754-c70525777059", | |
| "leftValue": "={{ $json.subject }}", | |
| "rightValue": "=Amex Alert Subject", | |
| "operator": { | |
| "type": "string", | |
| "operation": "contains" | |
| } | |
| } | |
| ], | |
| "combinator": "and" | |
| }, | |
| "renameOutput": true, | |
| "outputKey": "Amex" | |
| }, | |
| { | |
| "conditions": { | |
| "options": { | |
| "caseSensitive": true, | |
| "leftValue": "", | |
| "typeValidation": "strict", | |
| "version": 2 | |
| }, | |
| "conditions": [ | |
| { | |
| "id": "10300c45-209c-4643-93a0-ae7b474a062e", | |
| "leftValue": "={{ $json.subject }}", | |
| "rightValue": "Citi Alert Subject", | |
| "operator": { | |
| "type": "string", | |
| "operation": "contains" | |
| } | |
| } | |
| ], | |
| "combinator": "and" | |
| }, | |
| "renameOutput": true, | |
| "outputKey": "Citi" | |
| }, | |
| { | |
| "conditions": { | |
| "options": { | |
| "caseSensitive": true, | |
| "leftValue": "", | |
| "typeValidation": "strict", | |
| "version": 2 | |
| }, | |
| "conditions": [ | |
| { | |
| "id": "5d8ab884-97a4-4b1c-8e16-03c35a994b4d", | |
| "leftValue": "={{ $json.subject }}", | |
| "rightValue": "Transaction Alert", | |
| "operator": { | |
| "type": "string", | |
| "operation": "contains" | |
| } | |
| } | |
| ], | |
| "combinator": "and" | |
| }, | |
| "renameOutput": true, | |
| "outputKey": "Discover" | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.switch", | |
| "typeVersion": 3.3, | |
| "position": [ | |
| -176, | |
| 720 | |
| ], | |
| "id": "1a33496a-897d-41ee-ae18-b0e7cd761be1", | |
| "name": "Switch" | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "const input = $input.all()\nconst payees = input[0].json.data.payees\nconst accounts = input[1].json.data.accounts\nconst amount = input[2].json.data.amount\nconst payee = input[2].json.data.payee\nconst bank = input[2].json.data.bank\n\nlet account_id = null\nfor (const account of accounts) {\n if (account.name == bank) {\n account_id = account.id\n }\n}\n\nreturn {\n account_id,\n amount: amount, // doesn't account for credits\n payee: payee.replace(\"*\", \"\"),\n bank,\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 720, | |
| 656 | |
| ], | |
| "id": "5d845b17-2aa3-49f2-adc4-8958233814a1", | |
| "name": "Code in JavaScript" | |
| }, | |
| { | |
| "parameters": { | |
| "method": "POST", | |
| "url": "https://api.ynab.com/v1/budgets/YNAB_BUDGET_ID/transactions", | |
| "authentication": "predefinedCredentialType", | |
| "nodeCredentialType": "httpBearerAuth", | |
| "sendBody": true, | |
| "specifyBody": "json", | |
| "jsonBody": "={\n \"transaction\": {\n \"account_id\": \"{{ $json.account_id }}\",\n\"date\": \"{{ $now.format('yyyy-LL-dd') }}\",\n\"amount\": {{ $json.amount }},\n\"payee_name\": \"{{ $json.payee }}\",\n\"memo\": \"{{ $json.memo }}\"\n} \n}", | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.3, | |
| "position": [ | |
| 1616, | |
| 656 | |
| ], | |
| "id": "3be8075f-5e54-48e0-8957-4a1217d42316", | |
| "name": "HTTP Request" | |
| }, | |
| { | |
| "parameters": { | |
| "pollTimes": { | |
| "item": [ | |
| { | |
| "mode": "everyMinute" | |
| } | |
| ] | |
| }, | |
| "simple": false, | |
| "filters": {}, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.gmailTrigger", | |
| "typeVersion": 1.3, | |
| "position": [ | |
| -400, | |
| 752 | |
| ], | |
| "id": "1a1a4fe8-93d1-4176-8207-a3f751ba985f", | |
| "name": "Gmail Trigger" | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "sendAndWait", | |
| "chatId": "TELEGRAM_CHAT_ID", | |
| "message": "=New {{ $json.bank }} transaction\nPayee: {{ $json.payee }}\nAmount: {{ $json.amount }}\n\nPlease reply with the payee name to auto-add the transaction. Optionally include a memo. Will timeout in 5 minutes.", | |
| "responseType": "customForm", | |
| "formFields": { | |
| "values": [ | |
| { | |
| "fieldLabel": "Payee", | |
| "placeholder": "={{ $json.payee }}" | |
| }, | |
| { | |
| "fieldLabel": "Amount", | |
| "placeholder": "={{ $json.amount }}" | |
| }, | |
| { | |
| "fieldLabel": "Memo" | |
| } | |
| ] | |
| }, | |
| "options": { | |
| "limitWaitTime": { | |
| "values": { | |
| "resumeAmount": 45, | |
| "resumeUnit": "minutes" | |
| } | |
| } | |
| } | |
| }, | |
| "type": "n8n-nodes-base.telegram", | |
| "typeVersion": 1.2, | |
| "position": [ | |
| 944, | |
| 592 | |
| ], | |
| "id": "bbc809db-896b-480b-9231-49c6cd6c8fa0", | |
| "name": "Send Message", | |
| "webhookId": "REMOVED", | |
| "alwaysOutputData": false | |
| }, | |
| { | |
| "parameters": {}, | |
| "type": "n8n-nodes-base.merge", | |
| "typeVersion": 3.2, | |
| "position": [ | |
| 1168, | |
| 656 | |
| ], | |
| "id": "97199a62-71a3-4722-9372-35d5bd51a44a", | |
| "name": "Merge1" | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "const input = $input.all()\n\nif (!input[0].json.data) {\n input[0].json.data = {\n Payee: input[1].json.payee,\n Amount: input[1].json.amount,\n Memo: \"\",\n }\n} else {\n input[0].json.data = {\n Payee: input[0].json.data.Payee || input[1].json.payee,\n Amount: input[0].json.data.Amount || input[1].json.amount,\n Memo: input[0].json.data.Memo,\n }\n}\n\nreturn {\n account_id: input[1].json.account_id,\n payee: input[0].json.data.Payee,\n amount: parseFloat(input[0].json.data.Amount) * -1000,\n memo: input[0].json.data.Memo,\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 1392, | |
| 656 | |
| ], | |
| "id": "f9f9dc90-f090-49b1-8bcf-677525fcf7e2", | |
| "name": "Code in JavaScript1" | |
| }, | |
| { | |
| "parameters": { | |
| "conditions": { | |
| "options": { | |
| "caseSensitive": true, | |
| "leftValue": "", | |
| "typeValidation": "strict", | |
| "version": 2 | |
| }, | |
| "conditions": [ | |
| { | |
| "id": "b9cdf27c-b8a7-4fa6-8650-5c84a3ece028", | |
| "leftValue": "1", | |
| "rightValue": "1", | |
| "operator": { | |
| "type": "string", | |
| "operation": "equals", | |
| "name": "filter.operator.equals" | |
| } | |
| } | |
| ], | |
| "combinator": "and" | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.if", | |
| "typeVersion": 2.2, | |
| "position": [ | |
| 48, | |
| 272 | |
| ], | |
| "id": "6faec602-d7a8-45be-b8a2-ca99572ab1e7", | |
| "name": "Junction" | |
| }, | |
| { | |
| "parameters": { | |
| "mode": "runOnceForEachItem", | |
| "jsCode": "function extractMerchant(html) {\n // Regex explanation:\n // 1. Find the exact <span>Merchant</span>\n // 2. Match any characters (including newlines)\n // 3. Capture the NEXT <span>...</span>\n const regex = /<span[^>]*>\\s*Merchant\\s*<\\/span>[\\s\\S]*?<span[^>]*>(.*?)<\\/span>/i;\n\n const match = regex.exec(html);\n if (!match) return null;\n\n return match[1].trim();\n}\n\nconst body = $json[\"html\"]\n\nconst amount = body.match(/Amount:\\s+\\$(\\d+\\.\\d+)/)[1]\nconst payee = extractMerchant(body)\n\nreturn {\n data: {\n bank: \"Citi Costco Visa\",\n amount,\n payee, \n }\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 272, | |
| 944 | |
| ], | |
| "id": "2f162499-f1a9-4e58-af13-434dcb59186d", | |
| "name": "Parse Citi" | |
| }, | |
| { | |
| "parameters": { | |
| "mode": "runOnceForEachItem", | |
| "jsCode": "const body = $json[\"html\"]\n\nconst payee = body.match(/Merchant:\\s+([^<]+)/)[1]\nconst amount = body.match(/Amount:\\s+\\$(\\d+\\.\\d+)/)[1]\n\nreturn {\n data: {\n bank: \"Discover\",\n amount,\n payee, \n }\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 272, | |
| 1136 | |
| ], | |
| "id": "6737f836-cde2-41a5-a0c2-3cabed6b6cf6", | |
| "name": "Parse Discover" | |
| } | |
| ], | |
| "connections": { | |
| "Parse BoA Trx": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge", | |
| "type": "main", | |
| "index": 2 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Parse Amex Trx": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge", | |
| "type": "main", | |
| "index": 2 | |
| } | |
| ] | |
| ] | |
| }, | |
| "YNAB Payees": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "YNAB Accounts": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge", | |
| "type": "main", | |
| "index": 1 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Merge": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Code in JavaScript", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Switch": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Parse BoA Trx", | |
| "type": "main", | |
| "index": 0 | |
| }, | |
| { | |
| "node": "Junction", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Parse Amex Trx", | |
| "type": "main", | |
| "index": 0 | |
| }, | |
| { | |
| "node": "Junction", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Parse Citi", | |
| "type": "main", | |
| "index": 0 | |
| }, | |
| { | |
| "node": "Junction", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Junction", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Code in JavaScript": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Send Message", | |
| "type": "main", | |
| "index": 0 | |
| }, | |
| { | |
| "node": "Merge1", | |
| "type": "main", | |
| "index": 1 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Gmail Trigger": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Switch", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Send Message": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge1", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Merge1": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Code in JavaScript1", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Code in JavaScript1": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "HTTP Request", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Junction": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "YNAB Payees", | |
| "type": "main", | |
| "index": 0 | |
| }, | |
| { | |
| "node": "YNAB Accounts", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Parse Citi": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge", | |
| "type": "main", | |
| "index": 2 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Parse Discover": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Merge", | |
| "type": "main", | |
| "index": 2 | |
| } | |
| ] | |
| ] | |
| } | |
| }, | |
| "active": true, | |
| "settings": { | |
| "executionOrder": "v1" | |
| }, | |
| "versionId": "56a19910-8b7d-40e8-a4bf-abe7bb9c5611", | |
| "meta": { | |
| "templateCredsSetupCompleted": true, | |
| "instanceId": "f3a8e78c3a1b243e336773b7f26ea7b990b57cf6ae74b2f0e20ac9dec41dbfb6" | |
| }, | |
| "id": "6Xeu0RbaMJVl4ihM", | |
| "tags": [] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment