This workflow corresponds to n8n.io template #5517 — we link there as the canonical source.
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 →
{
"id": "E1CD2pH99IVoXnwp",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Personal expense tracker",
"tags": [],
"nodes": [
{
"id": "0dc9105c-6579-4bde-b831-b993ac6e1a54",
"name": "Expense Input Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
240,
100
],
"parameters": {
"path": "add-expense",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 1
},
{
"id": "17662aeb-97d6-468e-b1d1-2b82a44dfbb9",
"name": "Validate and Format Expense Data",
"type": "n8n-nodes-base.function",
"position": [
540,
100
],
"parameters": {
"functionCode": "// Validate and format expense data\nconst body = $input.first().json.body || {};\n\nconst expense = {\n date: body.date || new Date().toISOString().split('T')[0],\n category: body.category || 'Other',\n description: body.description || 'No description',\n amount: parseFloat(body.amount) || 0,\n payment_method: body.payment_method || 'Cash'\n};\n\n// Validate amount\nif (expense.amount <= 0) {\n throw new Error('Amount must be greater than 0');\n}\n\n// Validate category\nconst validCategories = ['Food', 'Transport', 'Shopping', 'Bills', 'Entertainment', 'Health', 'Other'];\nif (!validCategories.includes(expense.category)) {\n expense.category = 'Other';\n}\n\n// Format amount to 2 decimal places\nexpense.amount = Math.round(expense.amount * 100) / 100;\n\nreturn { json: expense };"
},
"typeVersion": 1
},
{
"id": "0a4044a1-f23e-4c5a-9383-425f0fb5cf9e",
"name": "Save Expense to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
840,
100
],
"parameters": {
"options": {
"cellFormat": "USER_ENTERED"
},
"operation": "append",
"sheetName": "Expenses",
"documentId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_YOUR_SPREADSHEET_ID"
}
},
"typeVersion": 4
},
{
"id": "84af3396-544e-41fe-a8ae-5f27f912bf77",
"name": "Calculate Monthly Summary",
"type": "n8n-nodes-base.function",
"position": [
1140,
100
],
"parameters": {
"functionCode": "// Calculate summary for current expense\nconst currentExpense = $('Validate and Format Expense Data').first().json;\nconst currentDate = new Date(currentExpense.date);\nconst currentMonth = currentDate.getMonth() + 1;\nconst currentYear = currentDate.getFullYear();\n\n// Create response with expense details and summary\nconst summary = {\n expense_added: currentExpense,\n monthly_summary: {\n month: currentMonth,\n year: currentYear,\n category: currentExpense.category,\n amount_added: currentExpense.amount,\n date_updated: new Date().toISOString()\n },\n success: true,\n message: `Expense of $${currentExpense.amount} for ${currentExpense.category} has been recorded successfully.`\n};\n\nreturn { json: summary };"
},
"typeVersion": 1
},
{
"id": "71a8e380-dc27-4cdb-a4e7-388347a38939",
"name": "Send Success Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1440,
100
],
"parameters": {
"options": {}
},
"typeVersion": 1
},
{
"id": "638d6c11-fcdc-4aa7-a785-6a23dad63e06",
"name": "Send Error Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
540,
260
],
"parameters": {
"options": {}
},
"typeVersion": 1
},
{
"id": "026567d0-aef6-49a8-9100-22cbac0bccae",
"name": "Daily Summary Schedule",
"type": "n8n-nodes-base.cron",
"position": [
240,
400
],
"parameters": {},
"typeVersion": 1
},
{
"id": "483b47d5-4b82-4e5b-9d79-fb1c2337d90a",
"name": "Read Today's Expenses from Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
540,
400
],
"parameters": {
"options": {},
"sheetName": "Expenses",
"documentId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_YOUR_SPREADSHEET_ID"
}
},
"typeVersion": 4
},
{
"id": "f166a60d-06f0-4852-88e2-c4a05fbf39c9",
"name": "Calculate Daily Total",
"type": "n8n-nodes-base.function",
"position": [
840,
400
],
"parameters": {
"functionCode": "// Filter and calculate today's expenses\nconst today = new Date().toISOString().split('T')[0];\nconst allExpenses = $input.all()[0].json || [];\n\n// Filter expenses for today\nconst todayExpenses = allExpenses.filter(expense => {\n return expense.date === today;\n});\n\n// Calculate total and by category\nconst categoryTotals = {};\nlet totalToday = 0;\n\ntodayExpenses.forEach(expense => {\n const amount = parseFloat(expense.amount || 0);\n totalToday += amount;\n \n if (!categoryTotals[expense.category]) {\n categoryTotals[expense.category] = 0;\n }\n categoryTotals[expense.category] += amount;\n});\n\nreturn {\n json: {\n date: today,\n total_expenses: Math.round(totalToday * 100) / 100,\n expense_count: todayExpenses.length,\n category_breakdown: categoryTotals,\n expenses: todayExpenses\n }\n};"
},
"typeVersion": 1
},
{
"id": "b395295d-2f98-41cf-9ea3-37aa8ba09e83",
"name": "Main Workflow Explanation",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-100
],
"parameters": {
"color": 4,
"width": 450,
"height": 1180,
"content": "# \ud83d\udcb0 Personal Expense Tracker API\n\n## What This Workflow Does\nProvides a complete expense tracking system with webhook API for adding expenses and automatic Google Sheets storage with daily summaries.\n\n## How It Works\n1. **API Endpoint**: Receives expenses via POST webhook\n2. **Data Validation**: Ensures proper format and categories\n3. **Google Sheets Storage**: Automatically saves to spreadsheet\n4. **Daily Reports**: Sends summary at 8 PM daily\n5. **Real-time Responses**: Returns success/error immediately\n\n## API Usage\nSend POST to: `/webhook/add-expense`\n```json\n{\n \"amount\": 25.50,\n \"category\": \"Food\",\n \"description\": \"Lunch at cafe\",\n \"payment_method\": \"Credit Card\"\n}\n```\n\n## Categories\n\u2022 Food \u2022 Transport \u2022 Shopping \u2022 Bills\n\u2022 Entertainment \u2022 Health \u2022 Other\n\n## Setup Required\n1. Create Google Sheets with 'Expenses' sheet\n2. Headers: Date | Category | Description | Amount | Payment Method\n3. Replace SPREADSHEET_ID in nodes\n4. Connect Google Sheets OAuth2\n5. Activate workflow\n\n## Perfect For\n\u2705 Personal finance tracking\n\u2705 Mobile app integration\n\u2705 Family expense sharing\n\u2705 Small business expense logging\n\n**Includes automatic validation, error handling, and daily summaries.**"
},
"typeVersion": 1
},
{
"id": "49605945-3d4d-497c-83f9-2518ebc4e1e9",
"name": "Step 1 - API Input",
"type": "n8n-nodes-base.stickyNote",
"position": [
200,
-220
],
"parameters": {
"color": 7,
"width": 300,
"height": 280,
"content": "## Step 1: API Input\n\n**Webhook** receives expense data via POST request\n\n**Endpoint**: `/webhook/add-expense`\n**Method**: POST\n**Format**: JSON\n\n*Perfect for mobile apps, web forms, or direct API calls*"
},
"typeVersion": 1
},
{
"id": "c02af8e8-6b84-4226-81cb-558bda710a91",
"name": "Step 2 - Data Validation",
"type": "n8n-nodes-base.stickyNote",
"position": [
500,
-200
],
"parameters": {
"color": 7,
"width": 300,
"height": 260,
"content": "## Step 2: Data Validation\n\n**Function Node** validates and cleans data:\n\u2022 Checks amount > 0\n\u2022 Validates categories\n\u2022 Sets defaults for missing fields\n\u2022 Formats numbers properly\n\n*Ensures data consistency*"
},
"typeVersion": 1
},
{
"id": "0ab3f049-da8f-48f0-9715-3fd5382310b8",
"name": "Step 3 - Google Sheets Storage",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
-220
],
"parameters": {
"color": 7,
"width": 300,
"height": 280,
"content": "## Step 3: Google Sheets Storage\n\n**Google Sheets Node** appends expense to spreadsheet\n\n**Sheet**: 'Expenses'\n**Columns**: Date | Category | Description | Amount | Payment Method\n\n*Your permanent expense database*"
},
"typeVersion": 1
},
{
"id": "f68eeb78-bf5c-43e6-8ac2-20745b3aa54f",
"name": "Step 4 - API Response",
"type": "n8n-nodes-base.stickyNote",
"position": [
1140,
-200
],
"parameters": {
"color": 7,
"width": 300,
"height": 260,
"content": "## Step 4: API Response\n\n**Response Nodes** return JSON with:\n\u2705 Success: Expense details + confirmation\n\u274c Error: Validation errors + field requirements\n\n*Immediate feedback for calling applications*"
},
"typeVersion": 1
},
{
"id": "d1a9d5fa-b4d8-492f-b3ed-9d8789194da3",
"name": "Daily Summary Automation",
"type": "n8n-nodes-base.stickyNote",
"position": [
1120,
280
],
"parameters": {
"color": 6,
"width": 500,
"height": 250,
"content": "## \ud83d\udcca Automated Daily Summary\n\n**Cron Trigger** runs daily at 8:00 PM to:\n\u2022 Read all today's expenses from Google Sheets\n\u2022 Calculate total spending and category breakdown\n\u2022 Generate summary report\n\n**Perfect for**: Evening expense review, budget tracking, spending pattern analysis\n\n*Stay informed about your daily spending habits automatically*"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "aedb5fd0-8999-486c-af50-b440d70e1926",
"connections": {
"Expense Input Webhook": {
"main": [
[
{
"node": "Validate and Format Expense Data",
"type": "main",
"index": 0
}
]
]
},
"Daily Summary Schedule": {
"main": [
[
{
"node": "Read Today's Expenses from Sheet",
"type": "main",
"index": 0
}
]
]
},
"Calculate Monthly Summary": {
"main": [
[
{
"node": "Send Success Response",
"type": "main",
"index": 0
}
]
]
},
"Save Expense to Google Sheets": {
"main": [
[
{
"node": "Calculate Monthly Summary",
"type": "main",
"index": 0
}
]
]
},
"Read Today's Expenses from Sheet": {
"main": [
[
{
"node": "Calculate Daily Total",
"type": "main",
"index": 0
}
]
]
},
"Validate and Format Expense Data": {
"main": [
[
{
"node": "Save Expense to Google Sheets",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
How it works: This system functions by receiving expenses via webhook POST. It validates the data, stores it in Google Sheets, and, daily at 8 PM, generates and sends financial summaries. Automatic categorization simplifies the organization of expenses. Set up steps: Setup…
Source: https://n8n.io/workflows/5517/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Automate WhatsApp communication for recruitment agencies with an interactive, structured customer experience. This workflow handles pricing inquiries, request submissions, tracking, complaints, and hu
Code. Uses googleSheets, gmail, supabase, stickyNote. Webhook trigger; 51 nodes.
This template turns Podium's conversation inbox into a full sales CRM with a custom funnel, AI message classification, automated drip follow-ups, daily admin reports, and a live Kanban dashboard. Six
Ticketing Backend automates registration, QR-ticket generation, email delivery, and check-in validation using Google Sheets, Gmail, and a webhook scanner — reducing manual ticket prep from ~3 hours to
> n8n + Gmail + Google Sheets + Typeform