This workflow corresponds to n8n.io template #17421 — we link there as the canonical source.
This workflow follows the HTTP Request → Telegram 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 →
{
"id": "MeQW2OGJvNbxJY6Q",
"name": "AI API Expense Tracker- FAL, APIFY and Open Router",
"tags": [],
"nodes": [
{
"id": "00ae67c6-bed3-41b1-a5d4-e9336710ea31",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 480,
"height": 768,
"content": "## Expense Tracker- FAL, APIFY and Open Router\n\n### How it works\n\nThis workflow runs on a schedule to track account expenses and remaining credits across FAL AI, OpenRouter, and Apify. It queries each provider API in sequence, consolidates the returned usage data with a JavaScript code node, and sends the resulting summary to Telegram.\n\n### Setup steps\n\n- Configure the Schedule Trigger with the desired checking frequency.\n- Add valid API authentication for the FAL AI billing request, OpenRouter credits request, and Apify usage request in their respective HTTP Request nodes.\n- Configure the Telegram node with bot credentials and the target chat ID for receiving the expense summary.\n- Review the JavaScript code node to ensure it matches the response formats returned by the three provider APIs.\n\n### Customization\n\nYou can adjust the schedule, add more provider credit endpoints, change the summary formatting in the JavaScript node, or route alerts to another notification channel instead of Telegram."
},
"typeVersion": 1
},
{
"id": "86e621b3-8cfc-4e74-a0d8-c23a0a08bf8c",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
0
],
"parameters": {
"color": 7,
"height": 368,
"content": "## Scheduled start\n\nStarts the workflow on a configured schedule so expense and credit balances can be checked automatically."
},
"typeVersion": 1
},
{
"id": "dab7f67a-838e-4857-82da-785f5ed46753",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
832,
80
],
"parameters": {
"color": 7,
"width": 640,
"height": 304,
"content": "## Fetch service credits\n\nCalls the FAL AI, OpenRouter, and Apify APIs in sequence to retrieve current billing, credits, and usage information from each service."
},
"typeVersion": 1
},
{
"id": "5441a46c-0899-43bf-97b7-746399946807",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1504,
48
],
"parameters": {
"color": 7,
"width": 400,
"height": 320,
"content": "## Format and notify\n\nCombines the collected API responses in JavaScript, prepares a readable summary, and sends it as a Telegram text message."
},
"typeVersion": 1
},
{
"id": "64047cdc-8642-460b-8bb5-13046e2440e4",
"name": "Fetch FAL AI Credits",
"type": "n8n-nodes-base.httpRequest",
"position": [
880,
208
],
"parameters": {
"url": "https://api.fal.ai/v1/account/billing?expand=credits",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Key YOUR API Key"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "f8b1de4a-d0ee-4d2b-bba2-3022f987791e",
"name": "Fetch Open Router Credits",
"type": "n8n-nodes-base.httpRequest",
"position": [
1120,
208
],
"parameters": {
"url": "https://openrouter.ai/api/v1/credits",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE API Key"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "cf6ede28-a305-4873-8753-3ec1ddc908e8",
"name": "Fetch APIFY Monthly Usage",
"type": "n8n-nodes-base.httpRequest",
"position": [
1328,
208
],
"parameters": {
"url": "https://api.apify.com/v2/users/me/usage/monthly",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "token",
"value": "YOUR API Key"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "f59b976b-7b78-4f6d-8c2e-5dd96acf7e30",
"name": "Collect Data in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
1552,
208
],
"parameters": {
"jsCode": "// 1. Safely collect ALL data from the workflow\nconst jsons = [];\ntry { jsons.push($items('FAL AI Credits')[0]?.json); } catch(e) {}\ntry { jsons.push($items('Open Router Credits')[0]?.json); } catch(e) {}\ntry { jsons.push($items('APIFY Credits')[0]?.json); } catch(e) {}\n\n// 2. DEEP SEARCH FUNCTION: Recursively hunts for exact keys\nfunction findValue(keys) {\n let result = null;\n function search(obj) {\n if (result !== null) return;\n if (typeof obj !== 'object' || obj === null) return;\n for (let k of keys) {\n if (obj[k] !== undefined && obj[k] !== null) {\n let val = parseFloat(obj[k]);\n if (!isNaN(val)) { result = val; return; }\n }\n }\n for (let k in obj) search(obj[k]);\n }\n jsons.forEach(search);\n return result;\n}\n\n// 3. Extract exact values from the proper billing endpoints\n// FAL AI\nconst falBalance = findValue(['current_balance']);\n\n// OpenRouter (/api/v1/credits returns 'total_credits' and 'total_usage')\nconst orTotalCredits = findValue(['total_credits']);\nconst orTotalUsage = findValue(['total_usage']);\n\n// Apify (/v2/users/me/usage/monthly returns USD amounts directly)\n// We look for 'totalUsageCreditsUsd' (Used) and 'monthlyUsageLimitUsd' or 'maxMonthlyUsageUsd' (Plan)\nconst apifyUsedUsd = findValue(['totalUsageCreditsUsd', 'totalUsageCreditsUsdAfterVolumeDiscount']);\n// To get the plan limit dynamically, we check the general limits (usually stored as maxMonthlyUsageUsd)\nconst apifyPlanUsd = findValue(['maxMonthlyUsageUsd', 'monthlyUsageLimitUsd', 'subscriptionLimitUsd']) ?? 29.00; // Apify usually hides the total plan limit in the /usage endpoint, but we grab the used USD directly.\n\n// 4. Calculate & Format Strings\nconst falStr = falBalance !== null ? `$${falBalance.toFixed(2)}` : 'N/A';\n\n// OpenRouter math: (total_credits - total_usage)\nlet orBalanceStr = 'N/A';\nlet orUsedStr = 'N/A';\nif (orTotalCredits !== null && orTotalUsage !== null) {\n orBalanceStr = `$${(orTotalCredits - orTotalUsage).toFixed(2)}`;\n orUsedStr = `$${orTotalUsage.toFixed(4)}`;\n}\n\n// Apify formatting\nconst apUsedStr = apifyUsedUsd !== null ? `$${apifyUsedUsd.toFixed(2)}` : 'N/A';\nconst apPlanStr = apifyPlanUsd !== null ? `$${apifyPlanUsd.toFixed(2)}` : 'N/A';\nconst apAvailStr = (apifyPlanUsd !== null && apifyUsedUsd !== null)\n ? `$${(apifyPlanUsd - apifyUsedUsd).toFixed(2)}`\n : 'N/A';\n\n// 5. Timestamp & Message\nconst now = new Date().toLocaleString('en-IN', {\n timeZone: 'Asia/Kolkata',\n day: '2-digit', month: 'short', year: 'numeric',\n hour: '2-digit', minute: '2-digit', hour12: true\n});\n\nconst message =\n`\ud83d\udcca <b>AI Tools \u2014 Daily Spend Report</b>\n\ud83d\udcc5 ${now}\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n\ud83c\udfa8 <b>FAL AI</b> <i>(Image Generation)</i>\n\u251c Balance Remaining: <b>${falStr}</b>\n\n\ud83e\udd16 <b>OpenRouter</b> <i>(LLM / AI Models)</i>\n\u251c Total Balance: <b>${orBalanceStr}</b>\n\u2514 Credits Used: <b>${orUsedStr}</b>\n\n\ud83d\udd77 <b>Apify</b> <i>(Web Scraping)</i>\n\u251c Monthly Plan: <b>${apPlanStr}</b>\n\u251c Used This Month: <b>${apUsedStr}</b>\n\u2514 Balance Available: <b>${apAvailStr}</b>\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83d\udccb <a href=\"https://docs.google.com/spreadsheets/d/1NzUyg2REHooSmN2DqOWWUAnrrvuuBLyUq6jtb1KR5Zw/edit?gid=0#gid=0\">View Google Sheet</a>`;\n\nreturn [{ json: { message } }];"
},
"typeVersion": 2
},
{
"id": "0e02b854-92bd-47f2-8f27-02149470f639",
"name": "Send Telegram Message",
"type": "n8n-nodes-base.telegram",
"position": [
1760,
208
],
"parameters": {
"text": "={{ $json.message }}",
"chatId": "YOUR CHAT ID",
"additionalFields": {
"parse_mode": "HTML",
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "27769036-8e0e-4604-bc97-bb68022515eb",
"name": "When Scheduled at 10:30 & 20:02",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
608,
208
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 10,
"triggerAtMinute": 30
},
{
"triggerAtHour": 20,
"triggerAtMinute": 2
}
]
}
},
"typeVersion": 1.3
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "f34b2455-ce0e-4b3c-8bd5-f123e3949d76",
"nodeGroups": [],
"connections": {
"Fetch FAL AI Credits": {
"main": [
[
{
"node": "Fetch Open Router Credits",
"type": "main",
"index": 0
}
]
]
},
"Fetch APIFY Monthly Usage": {
"main": [
[
{
"node": "Collect Data in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Fetch Open Router Credits": {
"main": [
[
{
"node": "Fetch APIFY Monthly Usage",
"type": "main",
"index": 0
}
]
]
},
"Collect Data in JavaScript": {
"main": [
[
{
"node": "Send Telegram Message",
"type": "main",
"index": 0
}
]
]
},
"When Scheduled at 10:30 & 20:02": {
"main": [
[
{
"node": "Fetch FAL AI Credits",
"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.
telegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs twice daily to fetch remaining credits and usage from FAL AI, OpenRouter, and Apify, then compiles a formatted spend report and sends it to a Telegram chat. Runs on a schedule at two specific times each day using a Schedule Trigger node configured for 10:30…
Source: https://n8n.io/workflows/17421/ — 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.
Women creators, homemakers-turned-entrepreneurs, and feminine lifestyle brands who want a graceful, low-lift way to keep an eye on competitor content and spark weekly ideas.
Reply to unanswered Skool posts with an LLM (human-approved). Uses @apify/n8n-nodes-apify, httpRequest, telegram. Scheduled trigger; 16 nodes.
🔥 Automated Daily Firecrawl Scraper with Telegram Alerts Get structured insights scraped daily from the web using Firecrawl’s AI extraction engine — then send them directly to your Telegram chat.
This workflow runs daily to fetch Instagram hashtag posts via the Apify API, computes a weighted engagement score, then sends a top-10 HTML report to Telegram and upserts the scored posts into Airtabl
How it works