AutomationFlowsAI & RAG › Record Transactions & Generate Budget Reports with Gemini Ai, Telegram &…

Record Transactions & Generate Budget Reports with Gemini Ai, Telegram &…

Original n8n title: Record Transactions & Generate Budget Reports with Gemini Ai, Telegram & Firefly Iii

ByPTS @pts on n8n.io

Anybody using Firefly III, especially home/self-hosted users, who want to add some level of automation to their transaction tracking, either in addition to or because they can't or don't want to use the dataimporter User sends a transaction screenshot/image or statement to a…

Event trigger★★★★☆ complexityAI-powered22 nodesTelegramGoogle GeminiHTTP RequestGoogle Gemini ChatTelegram TriggerAgentOutput Parser Structured
AI & RAG Trigger: Event Nodes: 22 Complexity: ★★★★☆ AI nodes: yes Added:
Record Transactions & Generate Budget Reports with Gemini Ai, Telegram &… — n8n workflow card showing Telegram, Google Gemini, HTTP Request integration

This workflow corresponds to n8n.io template #11339 — we link there as the canonical source.

This workflow follows the Agent → Googlegemini recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "tNM1ijEZ8gWfVxaM",
  "name": "AutoBudgetTelegram+Firefly",
  "tags": [
    {
      "id": "CJEsjBkYVWZdgNZa",
      "name": "LLM",
      "createdAt": "2025-11-28T18:56:28.956Z",
      "updatedAt": "2025-11-28T18:56:28.956Z"
    },
    {
      "id": "NPouo2sN6F8nYIw1",
      "name": "Telegram",
      "createdAt": "2025-11-28T18:56:31.687Z",
      "updatedAt": "2025-11-28T18:56:31.687Z"
    },
    {
      "id": "kXS4WSOIuW9HglP2",
      "name": "Templates",
      "createdAt": "2025-11-28T18:56:22.483Z",
      "updatedAt": "2025-11-28T18:56:22.483Z"
    },
    {
      "id": "nvgXicJYeK7nKBBf",
      "name": "HTTP",
      "createdAt": "2025-11-28T18:56:35.744Z",
      "updatedAt": "2025-11-28T18:56:35.744Z"
    },
    {
      "id": "ujpwDAZzATL8pDYI",
      "name": "Budget",
      "createdAt": "2025-11-28T19:18:18.314Z",
      "updatedAt": "2025-11-28T19:18:18.314Z"
    }
  ],
  "nodes": [
    {
      "id": "b840d397-569c-4819-a635-f01e3f2cd57d",
      "name": "Get file from server",
      "type": "n8n-nodes-base.telegram",
      "position": [
        736,
        688
      ],
      "parameters": {
        "fileId": "={{ $json.message.document.file_id }}",
        "resource": "file",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "dce037ba-70e5-48c8-acb6-802f6e1a0e65",
      "name": "Analyze the image or pdf",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        960,
        496
      ],
      "parameters": {
        "text": "## Role\nExtract transaction data as numbered list. Each transaction = separate line with criteria as sub-items.\n\n## Rules\nCriteria to extract:\n1. Billing Amount\n2. Transaction Date\n3. Payee\n4. Bank ID\n\n## Firefly III Bank ID\nBank ID = [123]\n\n## Image Processing (image/jpeg only)\nUse the following template  to identify the criteria:\n\n'Online Purchase\nCard: Visa\nAt: (3. Payee)\nTotal due amount: (1. Billing Amount)\nDate: (2. Transaction Date)'",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": ""
        },
        "options": {},
        "resource": "document",
        "simplify": false,
        "inputType": "binary"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "4ab87fc0-ebde-4e68-85d8-5b689d33e917",
      "name": "Make it pretty",
      "type": "n8n-nodes-base.code",
      "position": [
        1536,
        496
      ],
      "parameters": {
        "jsCode": "// n8n Code node - Transform transaction data\n\nconst data = $input.item.json;\n\nconst output = [];\n\nif (data.output && data.output.Transaction && Array.isArray(data.output.Transaction)) {\n  data.output.Transaction.forEach(transaction => {\n    output.push({\n      \"Type\": transaction.Type || \"\",\n      \"Date\": transaction.Date || \"\",\n      \"Payee\": transaction.Payee || \"\",\n      \"Amount\": transaction.Amount || \"\",\n      \"Account\": transaction.Account || \"\",\n      \"Description\": transaction.Description || \"\",\n      \"Category\": transaction.Category || \"\"\n    });\n  });\n}\n\nreturn output;"
      },
      "typeVersion": 2
    },
    {
      "id": "d755e1a4-bb53-4f7c-a650-a0c2c9fc142a",
      "name": "Get image from server",
      "type": "n8n-nodes-base.telegram",
      "position": [
        736,
        496
      ],
      "parameters": {
        "fileId": "={{ $json.message.photo[1].file_id }}",
        "resource": "file",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6386bc2a-d0b8-43f3-8f9e-3dc351301c66",
      "name": "Post to Firefly",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2000,
        608
      ],
      "parameters": {
        "url": "http[s]://[insert firefly url here]/api/v1/transactions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"transactions\": [\n    {\n      \"type\": \"{{ $('Make it pretty').item.json.Type }}\",\n      \"date\": \"{{ $json.Date }}\",\n      \"amount\": \"{{ $json.Amount }}\",\n      \"description\": \"{{ $json.Description }}\",\n      \"category_name\": \"{{ $json.Category }}\",\n      \"source_id\": {{ $json.Account }},\n      \"destination_name\": \"{{ $json.Payee }}\"\n    }\n  ]\n} ",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.api+json"
            },
            {
              "name": "Content-Type",
              "value": "=application/json"
            }
          ]
        }
      },
      "credentials": {
        "oAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "waitBetweenTries": 3000
    },
    {
      "id": "6f1db2c1-b443-4c7c-a01a-7fc55091d794",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        480,
        624
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Image",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "7c55453f-4e09-49d4-a641-f18c4f4b4ccf",
                    "operator": {
                      "type": "object",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.message.photo[0] }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "PDF",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "23528a51-6952-4243-83a2-1c6f506e2252",
                    "operator": {
                      "type": "object",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.message.document }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Report",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "75acbc61-4e26-45da-8575-f56a76e01074",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "Report"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "report",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "99beefa2-a758-462e-bab6-a285d3b1ebe8",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "report"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.3
    },
    {
      "id": "07b2493d-dec0-4bcd-af0d-1ba3c94d9e71",
      "name": "Analyzer Scraper",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1184,
        720
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "66c372e2-7b0d-461c-8e23-5fa159c0ce8f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        864
      ],
      "parameters": {
        "color": 7,
        "width": 1152,
        "height": 256,
        "content": "## 4. Bonus: Report Generation\nProduces a budget report from the beginning of the month to now if 'report' is sent to the telegram chat"
      },
      "typeVersion": 1
    },
    {
      "id": "cd42b9d9-fca9-4e4b-8277-8f60cad4cdc2",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 768,
        "height": 464,
        "content": "## 2. Image & PDF Processing\nPulls the image or document from Telegram servers. Gemini analyzes and parses the relevant info"
      },
      "typeVersion": 1
    },
    {
      "id": "114a012f-2a4c-42e5-aaf5-28815677f973",
      "name": "Loop for Multiple Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1760,
        496
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "ca8be60f-4fcf-49be-bde2-a944feeea88a",
      "name": "Confirmation Message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2000,
        448
      ],
      "parameters": {
        "text": "=Transaction(s) recorded",
        "chatId": "={{ $('Transaction Image or PDF Received').item.json.message.chat.id }}",
        "forceReply": {},
        "replyMarkup": "forceReply",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "cc18d851-e81d-4215-87b0-0c65f3272210",
      "name": "Get Remaining Budget",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        736,
        960
      ],
      "parameters": {
        "url": "http[s]://[insert firefly url here]/api/v1/budget-limits",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "queryParameters": {
          "parameters": [
            {
              "name": "start",
              "value": "={{ $now.year }}-{{ $now.month }}-01"
            },
            {
              "name": "end",
              "value": "={{ $now.year }}-{{ $now.month }}-{{ $now.day }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.api+json"
            },
            {
              "name": "Content-Type",
              "value": "application/vnd.api+json"
            }
          ]
        }
      },
      "credentials": {
        "oAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ab9ada0f-31e5-4b7c-b29d-108670b60217",
      "name": "Parse JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        960
      ],
      "parameters": {
        "jsCode": "// Get the input data - handle different possible structures\nconst items = $input.all();\nlet inputData;\n\n// Try to find the data in different possible locations\nif (items[0].json[0]) {\n  inputData = items[0].json[0];\n} else if (items[0].json) {\n  inputData = items[0].json;\n} else if (Array.isArray(items[0])) {\n  inputData = items[0][0];\n} else {\n  inputData = items[0];\n}\n\n// Check if we have the expected structure\nif (!inputData.included || !inputData.data) {\n  // Return the structure so you can see what you're receiving\n  return [{\n    error: \"Data structure not as expected\",\n    receivedKeys: Object.keys(inputData),\n    sampleData: inputData\n  }];\n}\n\n// Extract budget data with spending info\nconst budgets = inputData.included;\nconst budgetLimits = inputData.data;\n\n// Create a map of budget spending from limits data\nconst spendingMap = {};\nbudgetLimits.forEach(limit => {\n  const budgetId = limit.attributes.budget_id;\n  const spent = limit.attributes.spent;\n  const spentAmount = spent.length > 0 ? parseFloat(spent[0].sum) : 0;\n  const pcAmount = parseFloat(limit.attributes.pc_amount);\n  const pcSpent = limit.attributes.pc_spent.length > 0 ? Math.abs(parseFloat(limit.attributes.pc_spent[0].sum)) : 0;\n  \n  spendingMap[budgetId] = {\n    spent: Math.abs(spentAmount),\n    pcAmount: pcAmount,\n    pcSpent: pcSpent\n  };\n});\n\n// Transform into structured array\nconst parsedData = budgets.map(budget => {\n  const attrs = budget.attributes;\n  const budgetId = budget.id;\n  const pcAmount = parseFloat(attrs.pc_auto_budget_amount);\n  const pcSpent = spendingMap[budgetId]?.pcSpent || 0;\n  const pcRemaining = pcAmount - pcSpent;\n  const percentUsed = amount > 0 ? ((spent / amount) * 100).toFixed(1) : 0;\n  \n  return {\n    budgetCategory: attrs.name,\n    percentUsed: parseFloat(percentUsed),\n    pcAmount: parseFloat(pcAmount.toFixed(2)),\n    pcSpent: parseFloat(pcSpent.toFixed(2)),\n    pcRemaining: parseFloat(pcRemaining.toFixed(2)),\n    order: attrs.order,\n    pcCurrencyCode: attrs.primary_currency_code,\n    pcCurrencySymbol: attrs.primary_currency_symbol\n  };\n});\n\n// Sort by budget order\nparsedData.sort((a, b) => a.order - b.order);\n\n// Calculate totals\nconst totals = parsedData.reduce((acc, item) => {\n  acc.pcAmount += item.pcAmount;\n  acc.pcSpent += item.pcSpent;\n  acc.pcRemaining += item.pcRemaining;\n  return acc;\n}, { amount: 0, spent: 0, remaining: 0, pcAmount: 0, pcSpent: 0, pcRemaining: 0 });\n\n// Calculate overall percentage\nconst totalPercentUsed = totals.amount > 0 ? ((totals.spent / totals.amount) * 100).toFixed(1) : 0;\n\n// Add totals row\nparsedData.push({\n  budgetCategory: 'TOTAL',\n  percentUsed: parseFloat(totalPercentUsed),\n  pcAmount: parseFloat(totals.pcAmount.toFixed(2)),\n  pcSpent: parseFloat(totals.pcSpent.toFixed(2)),\n  pcRemaining: parseFloat(totals.pcRemaining.toFixed(2)),\n  order: 999,\n});\n\nreturn parsedData;"
      },
      "typeVersion": 2
    },
    {
      "id": "37e61de9-924c-4786-a50f-4abab4b0b4bc",
      "name": "Pull required fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1184,
        960
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "37f92d9d-4f7e-4fc1-8f22-7486315ac3ca",
              "name": "Bucket",
              "type": "string",
              "value": "={{ $json.budgetCategory }}"
            },
            {
              "id": "4e90b4da-c1a5-49e4-b584-0d5d75e86b29",
              "name": "Budget",
              "type": "number",
              "value": "={{ $json.pcAmount }}"
            },
            {
              "id": "361f590f-5502-4e6c-91c6-dca776aecead",
              "name": "Spent",
              "type": "number",
              "value": "={{ $json.pcSpent }}"
            },
            {
              "id": "7ce4bb41-473c-4679-9380-94a287ffe768",
              "name": "Remaining",
              "type": "number",
              "value": "={{ $json.pcRemaining }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "22624e96-30d2-4251-a114-dd057749a605",
      "name": "Make CSV",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        1408,
        960
      ],
      "parameters": {
        "options": {
          "fileName": "=Budget report for {{ $now.monthLong }} 01 to {{ $now.day }}.csv"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "c6f611a6-d37b-4bf3-bad3-4497a86af766",
      "name": "Send CSV",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1632,
        960
      ],
      "parameters": {
        "chatId": "={{ $('Transaction Image or PDF Received').item.json.message.chat.id }}",
        "operation": "sendDocument",
        "binaryData": true,
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "7ae2a7f0-eb96-4210-8e23-e3f962417c45",
      "name": "Transaction Image or PDF Received",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        256,
        656
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "71222495-5178-441b-87e2-66ce43ad74bd",
      "name": "Parse details & add category",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1184,
        496
      ],
      "parameters": {
        "text": "={{ $json.candidates[0].content.parts[0].text }}\n\nHere is the transaction description(s): {{ $('Transaction Image or PDF Received').item.json.message.caption }}",
        "options": {
          "systemMessage": "=## Role\nParse transactions into structured components: Billing Amount, Payee, Transaction Date (yyyy-mm-dd), Bank ID, Category, Transaction Type, Description.\n\n## Rules\n- Remove currency symbols\n- Year is always 2025+\n\nTransaction Type:\n- withdrawal = purchases/spending\n- deposit = salary/income/interest\n- transfer = internal transfers\n\nDescription: \n- If numbered descriptions = multiple transactions (in order)\n- Not numbered = single transaction\n- If no description, identify number of transactions and create a description for each\n\nCategories (select one):\nTaxi, Phone & Telecom, Pet Expenses, Food Delivery, Groceries, Home Goods, Electronics, Health, Makeup, Clothes, Beauty & Salon, Car Expenses, Holidays, Coffee, Entertainment & Going Out, Rent, Salary, Cashback & Interest, Family Transfer\n\nCategory notes:\n- Health = medicines, mental health, doctor visits\n- Car Expenses = car-related expenses including gas/petrol\n\n#Special overrides:\n#- Include if necessary or delete\n\n#Deposit overrides:\n#- Include if necessary or delete"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 2.2
    },
    {
      "id": "56c34be1-e6c5-46b3-ba3b-4a14ca9c6779",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        384
      ],
      "parameters": {
        "width": 752,
        "height": 720,
        "content": "# Automated Transaction Posting in Firefly III\n\n## How it works\n1. **Send a transaction** image (screenshot) or pdf statement to Telegram\n2. Gemini Analyzes and Parses the transaction data\n3. Relevant info is structured and posted to Firefly III\n4. Bonus: sending the word 'Report' to the Telegram channel creates a budget report of the month-to-date\n\n## Setup\n- [ ] Go into each Telegram node and either create or select the Telegram credential you want to use\n- [ ] Go into each HTTP node and \n  - under `OAuth2 API` select or create your Firefly OAuth2 credential. Use this link to find out how to create one if necessary https://docs.firefly-iii.org/how-to/firefly-iii/features/api/#create-an-oauth2-client\n  - insert your Firefly domain ONLY where it says `[insert firefly url here]`\n  - remove the bracket around `s` in `http[s]` if using a secure connection, or remove the `[s]` if using a local/unsecured http connection\n- [ ] Go into the `Analyze the image or pdf` node and select or create your Gemini credential and then select the model you wish to use\n- [ ] Go into the `Analyzer Scraper` node and select or create your Gemini credential and then select the model you wish to use\n\n\n## Customization\n- [ ] modify the rules in the 'Analyze the image or pdf' as relates to your Firefly account. At the least, provide Bank ID as per your asset account in Firefly (if you click on your asset account, the ID number is the 2 or 3 digit number in the URL)\n- [ ] Go into the `Parse details & add category` node\n  - modify the 'Categories' area to match your needs\n  - add any special overrides as needed (i.e. if 'Payee = UBER', set 'Category' to 'Transportation') or delete\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d99b0e30-8550-4fa5-946b-ac79fd05ddf2",
      "name": "Parse Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1328,
        720
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"Transaction\": [\n      {\n        \"Type\": \"Transaction Type\",\n        \"Amount\": \"Billing Amount (SAR)\",\n        \"Payee\": \"Payee\",\n        \"Date\": \"Transaction Date\",\n        \"Account\": \"Bank ID\",\n        \"Description\": \"Description\",\n        \"Category\": \"None\"\n      }\n    ]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "9a206719-7243-4ad7-8ebd-a8d801116a97",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 464,
        "content": "## 3. Formatting and posting\nThe info is formatted to fit the Firefly III requirements. Each transaction is posted 1 by 1, with a confirmation of each record sent back to the Telegram channel"
      },
      "typeVersion": 1
    },
    {
      "id": "9e5ad62b-f75e-4ada-82b4-a18b16ac03c2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        528
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 336,
        "content": "## 1. Manual Trigger\nImage, PDF or Text sent by user to Telegram channel\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "97401c0a-d777-4aee-b543-43eaa80c5483",
  "connections": {
    "Switch": {
      "main": [
        [
          {
            "node": "Get image from server",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get file from server",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Remaining Budget",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Remaining Budget",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Make CSV": {
      "main": [
        [
          {
            "node": "Send CSV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse JSON": {
      "main": [
        [
          {
            "node": "Pull required fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Output": {
      "ai_outputParser": [
        [
          {
            "node": "Parse details & add category",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Make it pretty": {
      "main": [
        [
          {
            "node": "Loop for Multiple Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Firefly": {
      "main": [
        [
          {
            "node": "Loop for Multiple Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyzer Scraper": {
      "ai_languageModel": [
        [
          {
            "node": "Parse details & add category",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Remaining Budget": {
      "main": [
        [
          {
            "node": "Parse JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get file from server": {
      "main": [
        [
          {
            "node": "Analyze the image or pdf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pull required fields": {
      "main": [
        [
          {
            "node": "Make CSV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get image from server": {
      "main": [
        [
          {
            "node": "Analyze the image or pdf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop for Multiple Items": {
      "main": [
        [
          {
            "node": "Confirmation Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post to Firefly",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze the image or pdf": {
      "main": [
        [
          {
            "node": "Parse details & add category",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse details & add category": {
      "main": [
        [
          {
            "node": "Make it pretty",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transaction Image or PDF Received": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Anybody using Firefly III, especially home/self-hosted users, who want to add some level of automation to their transaction tracking, either in addition to or because they can't or don't want to use the dataimporter User sends a transaction screenshot/image or statement to a…

Source: https://n8n.io/workflows/11339/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This project is a template for building a complete academic virtual assistant using n8n. It connects to Telegram, answers frequently asked questions by querying MongoDB, keeps the community informed a

Telegram, MongoDB, Telegram Trigger +6
AI & RAG

Creators, marketers, and brands that want to turn a single product photo into premium motion clips, then optionally publish to Instagram/TikTok/YouTube via LATE. No editing skills required.

Telegram, Agent Tool, Telegram Trigger +5
AI & RAG

Product to Social Video (xCodeWraith Edition). Uses telegram, agentTool, telegramTrigger, httpRequest. Event-driven trigger; 83 nodes.

Telegram, Agent Tool, Telegram Trigger +5
AI & RAG

This workflow transforms your Telegram bot into an intelligent creative assistant. It can chat conversationally, fetch trending image prompts from PromptHero for inspiration, or perform a deep "remix"

Telegram Trigger, Output Parser Structured, Telegram +6
AI & RAG

This automation is designed to help you generate AI-powered music tracks, cover art, and fully rendered music videos — all triggered from a simple Telegram chat and managed via Google Sheets.

OpenAI Chat, Memory Buffer Window, Output Parser Structured +11