Bank & wallet SMS → money tracker
Forward bank, card and wallet SMS to a webhook; AI logs each payment and income in a sheet.
How it works
- An SMS-forwarding app on your phone sends bank and wallet SMS to the webhook.
- AI reads the SMS: income or expense, amount, currency, merchant and date.
- OTPs, ads and balance messages are ignored; transactions go to your Money sheet.
Diagram
Code
JavaScript used in the Code step — already included in the template below.
// Mode: Run Once for Each Item
// The AI was asked for JSON like:
// {"is_transaction": true, "type": "debit", "amount": 450, "currency": "EGP", "merchant": "Carrefour", "date": "2026-10-19"}
const match = $json.text.match(/\{[\s\S]*\}/);
const t = match ? JSON.parse(match[0]) : {};
const sms = $("Bank SMS").item.json.body || {};
return {
json: {
is_transaction: t.is_transaction === true && Number(t.amount) > 0,
date: t.date || new Date().toISOString().slice(0, 10),
type: t.type === "credit" ? "income" : "expense",
amount: Number(t.amount) || 0,
currency: t.currency || "EGP",
merchant: t.merchant || "",
sender: sms.from || "",
},
};Build it
Pick your tool — same automation, step by step.
Copy and paste straight into an n8n canvas (Ctrl+V), or download and use Import from File. Then connect your own credentials and replace every YOUR_… placeholder. AI steps use a Claude model node — swap it for OpenAI, Gemini or Ollama if you prefer.
Show code (208 lines)
{
"name": "Bank & wallet SMS → money tracker (Flowngn)",
"nodes": [
{
"parameters": {
"content": "## Bank & wallet SMS → money tracker\nForward bank, card and wallet SMS to a webhook; AI logs each payment and income in a sheet.\n\n**Setup**\n1. Open each node and connect your own credentials.\n2. Replace every YOUR_… placeholder.\n3. Test once, then activate.\n\nFree template from Flowngn",
"height": 260,
"width": 340
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Setup notes",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-420,
-60
]
},
{
"parameters": {
"httpMethod": "POST",
"path": "bank-sms",
"options": {}
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Bank SMS",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"webhookId": "2de5ab85-b2af-45d3-a2c6-711a884b6523"
},
{
"parameters": {
"promptType": "define",
"text": "=This is a bank, card or wallet SMS (often Arabic or English). Reply ONLY with JSON: {\"is_transaction\": true|false, \"type\": \"debit\"|\"credit\", \"amount\": number, \"currency\": \"EGP\", \"merchant\": \"...\", \"date\": \"YYYY-MM-DD\"}. OTP codes, ads and balance-only messages are not transactions.\n\nSMS: {{ $json.body.text }}"
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Read the SMS",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.5,
"position": [
300,
0
]
},
{
"parameters": {
"model": {
"__rl": true,
"value": "claude-sonnet-5",
"mode": "list"
},
"options": {}
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Claude model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"typeVersion": 1.3,
"position": [
300,
220
]
},
{
"parameters": {
"jsCode": "// Mode: Run Once for Each Item\n// The AI was asked for JSON like:\n// {\"is_transaction\": true, \"type\": \"debit\", \"amount\": 450, \"currency\": \"EGP\", \"merchant\": \"Carrefour\", \"date\": \"2026-10-19\"}\nconst match = $json.text.match(/\\{[\\s\\S]*\\}/);\nconst t = match ? JSON.parse(match[0]) : {};\nconst sms = $(\"Bank SMS\").item.json.body || {};\n\nreturn {\n json: {\n is_transaction: t.is_transaction === true && Number(t.amount) > 0,\n date: t.date || new Date().toISOString().slice(0, 10),\n type: t.type === \"credit\" ? \"income\" : \"expense\",\n amount: Number(t.amount) || 0,\n currency: t.currency || \"EGP\",\n merchant: t.merchant || \"\",\n sender: sms.from || \"\",\n },\n};",
"mode": "runOnceForEachItem"
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Read transaction",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
600,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "c1",
"leftValue": "={{ $json.is_transaction }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Is a transaction?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
900,
0
]
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Money",
"mode": "name"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {}
},
"options": {}
},
"id": "2de5ab85-b2af-45d3-a2c6-711a884b6523",
"name": "Add to Money sheet",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1200,
0
]
}
],
"connections": {
"Bank SMS": {
"main": [
[
{
"node": "Read the SMS",
"type": "main",
"index": 0
}
]
]
},
"Read the SMS": {
"main": [
[
{
"node": "Read transaction",
"type": "main",
"index": 0
}
]
]
},
"Read transaction": {
"main": [
[
{
"node": "Is a transaction?",
"type": "main",
"index": 0
}
]
]
},
"Is a transaction?": {
"main": [
[
{
"node": "Add to Money sheet",
"type": "main",
"index": 0
}
]
]
},
"Claude model": {
"ai_languageModel": [
[
{
"node": "Read the SMS",
"type": "ai_languageModel",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": false
},
"tags": []
}In Make, create a new scenario and add these modules in order:
- Webhooks › Custom webhook
- Anthropic Claude › Create a Prompt (or OpenAI › Create a Completion)
- Tools › Set variable / Iterator + Array aggregator (same logic as the Code step)
- Filter on the next route: “Is a transaction?”
- If yesGoogle Sheets › Add a Row
- Every module run uses Make operations — the free plan includes a monthly quota.
- Make's built-in functions (map, sum, formatDate…) can replace most Code steps; for complex logic use a code module.
- Module and step names can differ slightly as Make and Zapier update their apps.
In Zapier, create a new Zap and add these steps in order:
- Webhooks by Zapier — Catch Hook
- Anthropic (Claude) — Send Message (or ChatGPT — Conversation)
- Code by Zapier — Run JavaScript (paste the code from the Code section)
- Filter by Zapier: “Is a transaction?”
- If yesGoogle Sheets — Create Spreadsheet Row
- Zaps with more than two steps need a paid Zapier plan.
- Webhooks, Filters/Paths and Code by Zapier are premium features on some Zapier plans.
- Code by Zapier runs JavaScript: reuse the code shown above, reading inputs from inputData instead of $json.
- Module and step names can differ slightly as Make and Zapier update their apps.
Tips
- Use an SMS forwarder app that filters by sender (your bank's name) — never forward OTP codes anywhere.
- Send only to your own private webhook URL.
Related flows
AI reads receipt emails into your expense sheet
AI pulls the vendor, amount, currency and date out of receipt emails and logs them.
Instant alert when a Stripe payment fails
Know about failed payments right away and log them for follow-up.
Paid invoices into your bookkeeping sheet
Every paid Stripe invoice is recorded automatically, ready for your accountant.