This workflow follows the HTTP Request → Postgres 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 →
{
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "callback-router",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-5152,
8144
],
"id": "1b5778cf-24da-4410-91f0-23caa81efe29",
"name": "Callback Router Webhook"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "has-route",
"leftValue": "={{ $json.route }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
-4752,
8144
],
"id": "bddced15-a99e-41a3-b822-406d691cb3ab",
"name": "Has Route?"
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.N8N_WEBHOOK_URL }}{{ $json.route }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ body: { telegram_id: $json.telegram_id, chat_id: $json.chat_id, message_id: $json.message_id, callback_query_id: $json.callback_query_id, callback_data: $json.callback_data } }) }}",
"options": {
"timeout": 30000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-4560,
8064
],
"id": "18da6dfe-d57c-4f96-b28c-95e32df4f395",
"name": "Forward to Handler"
},
{
"parameters": {
"jsCode": "// Unknown callback prefix - log for debugging\nconst data = $('Parse Callback1').item.json;\n\nconsole.log('Unknown callback prefix:', data.prefix);\nconsole.log('Full callback data:', data.callback_data);\n\nreturn {\n json: {\n error: 'Unknown callback prefix',\n prefix: data.prefix,\n callback_data: data.callback_data\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-4560,
8224
],
"id": "30c5b5cc-3b69-4de1-993d-14d173980a89",
"name": "Log Unknown"
},
{
"parameters": {
"content": "# Callback Router\nRoutes all callback queries to the appropriate handler workflows",
"height": 96,
"width": 500,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-5168,
8016
],
"id": "f975a5e4-a335-4604-9b08-8057a9c8121c",
"name": "Sticky Note18"
},
{
"parameters": {
"jsCode": "const callbackData = $input.first().json.body.callback_query.data;\nconst prefix = callbackData.split('|')[0];\n\n// Map prefixes to webhook endpoints\nconst routeMap = {\n 'settings': '/webhook/settings-callback',\n 'focus': '/webhook/focus-callback',\n 'sunnah': '/webhook/sunnah-callback', \n 'masjid': '/webhook/masjid-callback', \n 'azkar': '/webhook/azkar-callback',\n 'fasting': '/webhook/fasting-callback',\n 'quran': '/webhook/quran-callback',\n 'hadith': '/webhook/hadith-callback',\n 'dua': '/webhook/dua-callback',\n 'gender': '/webhook/gender-callback' // \u2190 ADD THIS LINE\n};\n\nconst route = routeMap[prefix] || null;\n\nreturn {\n json: {\n prefix: prefix,\n route: route,\n callback_data: callbackData,\n telegram_id: $input.first().json.body.callback_query.message.chat.id,\n chat_id: $input.first().json.body.callback_query.message.chat.id,\n message_id: $input.first().json.body.callback_query.message.message_id,\n callback_query_id: $input.first().json.body.callback_query.id,\n full_callback: $input.first().json.body.callback_query\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-4960,
8144
],
"id": "5c5c1505-1567-45e7-b85f-5bfc94153721",
"name": "Parse Callback1"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true }) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
-4352,
8144
],
"id": "21ed837d-1b40-4d03-878f-110c263cea8f",
"name": "Respond6"
},
{
"parameters": {
"content": "# Settings Menu Handler\nHandles /settings command and displays user preferences with profile editing",
"height": 96,
"width": 628,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-5168,
7680
],
"id": "5e3066b5-4d65-4d1f-ac74-8ab090f65e1c",
"name": "Sticky Note"
},
{
"parameters": {
"httpMethod": "POST",
"path": "settings-menu",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-5152,
7808
],
"id": "8fb3e680-4f44-4862-8c69-58b2cd2b30ea",
"name": "Settings Webhook"
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT \n u.telegram_id,\n u.first_name,\n u.gender,\n u.city,\n u.consecutive_perfect_days,\n u.azkar_enabled,\n u.sunnah_enabled,\n u.masjid_prayer_enabled,\n u.period_mode_active,\n u.is_paused\nFROM users u\nWHERE u.telegram_id = $1;",
"options": {
"queryReplacement": "={{ $json.body.body.telegram_id }}"
}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
-4976,
7808
],
"id": "c9b5a402-00eb-4e95-990d-b9a00053a1ab",
"name": "Get User Settings",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const user = $input.first().json;\nconst gender = user.gender;\nconst daysStreak = user.consecutive_perfect_days || 0;\nconst isPaused = user.is_paused || false;\n\n// Build keyboard rows\nconst keyboard = [];\n\n// === PAUSE/RESUME TOGGLE ===\nconst pauseStatus = isPaused ? '\u25b6\ufe0f' : '\u23f8\ufe0f';\nconst pauseText = isPaused ? '\u0627\u0633\u062a\u0626\u0646\u0627\u0641 \u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a' : '\u0625\u064a\u0642\u0627\u0641 \u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a';\nkeyboard.push([{\n text: `${pauseStatus} ${pauseText}`,\n callback_data: 'settings|pause|toggle'\n}]);\n\n// === PROFILE SECTION (with gender icon) ===\nkeyboard.push([\n { text: '\ud83d\udccd \u0627\u0644\u0645\u0648\u0642\u0639', callback_data: 'settings|profile|location' },\n { text: '\u270f\ufe0f \u0627\u0644\u0627\u0633\u0645', callback_data: 'settings|profile|name' },\n { text: gender === 'male' ? '\ud83d\udc68' : '\ud83d\udc69', callback_data: 'settings|profile|gender' }\n]);\n\n// === PERIOD MODE FOR FEMALES ===\nif (gender === 'female') {\n const periodStatus = user.period_mode_active ? '\u2705' : '\u274c';\n keyboard.push([{\n text: `${periodStatus} \u0639\u0630\u0631 \u0634\u0631\u0639\u064a`,\n callback_data: 'settings|period|toggle'\n }]);\n}\n\n// === FEATURES SECTION ===\nconst azkarStatus = user.azkar_enabled ? '\u2705' : '\u274c';\nkeyboard.push([{\n text: `${azkarStatus} \u062a\u0646\u0628\u064a\u0647\u0627\u062a \u0627\u0644\u0623\u0630\u0643\u0627\u0631`,\n callback_data: 'settings|azkar|toggle'\n}]);\n\nconst sunnahStatus = user.sunnah_enabled ? '\u2705' : '\u274c';\nkeyboard.push([{\n text: `${sunnahStatus} \u062a\u062a\u0628\u0639 \u0635\u0644\u0648\u0627\u062a \u0627\u0644\u0633\u0646\u0629`,\n callback_data: 'settings|sunnah|toggle'\n}]);\n\nif (gender === 'male') {\n const masjidStatus = user.masjid_prayer_enabled ? '\u2705' : '\u274c';\n keyboard.push([{\n text: `${masjidStatus} \u062a\u062a\u0628\u0639 \u0635\u0644\u0627\u0629 \u0627\u0644\u062c\u0645\u0627\u0639\u0629`,\n callback_data: 'settings|masjid|toggle'\n }]);\n}\n\n// Close button\nkeyboard.push([{\n text: '\u274c \u0625\u063a\u0644\u0627\u0642',\n callback_data: 'settings|close'\n}]);\n\n// Build message\nconst cityName = user.city || '\u063a\u064a\u0631 \u0645\u062d\u062f\u062f';\nconst genderText = gender === 'male' ? '\u0630\u0643\u0631' : (gender === 'female' ? '\u0623\u0646\u062b\u0649' : '\u063a\u064a\u0631 \u0645\u062d\u062f\u062f');\n\nlet message = `\u2699\ufe0f *\u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a*\\n\\n`;\nmessage += `\ud83d\udc64 ${user.first_name} (${genderText})\\n`;\nmessage += `\ud83d\udccd ${cityName}\\n`;\nmessage += `\ud83d\udd25 \u0623\u064a\u0627\u0645 \u0645\u062a\u062a\u0627\u0644\u064a\u0629: ${daysStreak}\\n`;\n\nif (isPaused) {\n message += `\\n\u23f8\ufe0f *\u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a \u0645\u062a\u0648\u0642\u0641\u0629*\\n`;\n}\n\nif (gender === 'female' && user.period_mode_active) {\n message += `\\n\ud83c\udf38 *\u0648\u0636\u0639 \u0627\u0644\u0639\u0630\u0631 \u0627\u0644\u0634\u0631\u0639\u064a \u0645\u0641\u0639\u0651\u0644*\\n`;\n}\n\nmessage += `\\n\u0627\u0636\u063a\u0637 \u0639\u0644\u0649 \u0623\u064a \u062e\u064a\u0627\u0631 \u0644\u062a\u0641\u0639\u064a\u0644\u0647 \u0623\u0648 \u0625\u0644\u063a\u0627\u0626\u0647:`;\n\nreturn {\n json: {\n telegram_id: user.telegram_id,\n message: message,\n keyboard: keyboard\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-4800,
7808
],
"id": "dd5ef84d-687d-4259-b529-9706a0345301",
"name": "Build Settings Menu"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true }) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
-4464,
7808
],
"id": "462379b7-5d4e-4ce0-96ff-ed6089d59a18",
"name": "Respond"
},
{
"parameters": {
"httpMethod": "POST",
"path": "settings-callback",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-4160,
7808
],
"id": "558a9d6a-8a2a-4e94-a50a-0680c99cdbbe",
"name": "Settings Callback Webhook"
},
{
"parameters": {
"jsCode": "// Data is nested under body.body\nconst callback = $json.body.body;\nconst data = callback.callback_data.split('|');\n\n// Format: settings|feature|action\n// e.g., settings|azkar|toggle, settings|locked|focus, settings|close\n// e.g., settings|profile|name, settings|profile|location\n\nreturn {\n json: {\n telegram_id: callback.telegram_id,\n chat_id: callback.chat_id,\n message_id: callback.message_id,\n callback_query_id: callback.callback_query_id,\n feature: data[1],\n action: data[2] || 'info',\n callback_data: callback.callback_data\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-3872,
7808
],
"id": "84cd94c7-0ea9-4063-bb04-1b649d8bf174",
"name": "Parse Callback"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cb-toggle",
"leftValue": "={{ $json.action }}",
"rightValue": "toggle",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "TOGGLE"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cb-locked",
"leftValue": "={{ $json.feature }}",
"rightValue": "locked",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "LOCKED"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cb-close",
"leftValue": "={{ $json.feature }}",
"rightValue": "close",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "CLOSE"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cb-profile",
"leftValue": "={{ $json.feature }}",
"rightValue": "profile",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "PROFILE"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cb-noop",
"leftValue": "={{ $json.feature }}",
"rightValue": "noop",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "NOOP"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.3,
"position": [
-3600,
7744
],
"id": "0483af1f-bbe6-46d8-9e73-741e2f72ec0e",
"name": "Callback Router"
},
{
"parameters": {
"jsCode": "const feature = $json.feature;\n\n// Map feature to database column\nconst featureToColumn = {\n 'azkar': 'azkar_enabled',\n 'sunnah': 'sunnah_enabled',\n 'masjid': 'masjid_prayer_enabled',\n 'period': 'period_mode_active',\n 'pause': 'is_paused'\n};\n\nconst featureNames = {\n 'azkar': '\u062a\u0646\u0628\u064a\u0647\u0627\u062a \u0627\u0644\u0623\u0630\u0643\u0627\u0631',\n 'sunnah': '\u062a\u062a\u0628\u0639 \u0635\u0644\u0648\u0627\u062a \u0627\u0644\u0633\u0646\u0629',\n 'masjid': '\u062a\u062a\u0628\u0639 \u0635\u0644\u0627\u0629 \u0627\u0644\u062c\u0645\u0627\u0639\u0629',\n 'period': '\u0648\u0636\u0639 \u0627\u0644\u0639\u0630\u0631 \u0627\u0644\u0634\u0631\u0639\u064a',\n 'pause': '\u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a'\n};\n\nconst column = featureToColumn[feature];\nconst featureName = featureNames[feature];\n\nif (!column) {\n return { json: { error: true, message: 'Unknown feature' } };\n}\n\nreturn {\n json: {\n ...$json,\n column: column,\n featureName: featureName,\n feature: feature\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-3360,
7664
],
"id": "ee755ace-6ab4-4511-b9aa-587fc59e778a",
"name": "Map Feature to Column"
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE users \nSET {{ $json.column }} = NOT {{ $json.column }}\nWHERE telegram_id = $1\nRETURNING {{ $json.column }} as new_value;",
"options": {
"queryReplacement": "={{ $json.telegram_id }}"
}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
-3168,
7664
],
"id": "98c80d71-b28e-44ab-98c9-ced3cd26af83",
"name": "Toggle Setting",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const newValue = $json.new_value;\nconst feature = $('Map Feature to Column').item.json.feature;\nconst featureName = $('Map Feature to Column').item.json.featureName;\nconst callbackQueryId = $('Parse Callback').item.json.callback_query_id;\n\nlet message;\n\nif (feature === 'pause') {\n // Special handling for pause toggle\n message = newValue ? '\u23f8\ufe0f \u062a\u0645 \u0625\u064a\u0642\u0627\u0641 \u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a' : '\u25b6\ufe0f \u062a\u0645 \u0627\u0633\u062a\u0626\u0646\u0627\u0641 \u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a';\n} else {\n const status = newValue ? '\u2705 \u062a\u0645 \u062a\u0641\u0639\u064a\u0644' : '\u274c \u062a\u0645 \u0625\u064a\u0642\u0627\u0641';\n message = `${status} ${featureName}`;\n}\n\nreturn {\n json: {\n telegram_id: $('Parse Callback').item.json.telegram_id,\n chat_id: $('Parse Callback').item.json.chat_id,\n message_id: $('Parse Callback').item.json.message_id,\n callback_query_id: callbackQueryId,\n answer_text: message,\n refresh_menu: true,\n feature: feature,\n new_value: newValue\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-2992,
7664
],
"id": "353ed5de-59ba-420c-9436-b29db9341dc0",
"name": "Build Toggle Response"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "callback_query_id",
"value": "={{ $json.callback_query_id }}"
},
{
"name": "text",
"value": "={{ $json.answer_text }}"
},
{
"name": "show_alert",
"value": "false"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-2800,
7824
],
"id": "8a2cb46d-cf81-408b-975c-c2e7b5776130",
"name": "Answer Callback"
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT \n u.telegram_id,\n u.first_name,\n u.gender,\n u.city,\n u.consecutive_perfect_days,\n u.azkar_enabled,\n u.sunnah_enabled,\n u.masjid_prayer_enabled,\n u.period_mode_active,\n u.is_paused\nFROM users u\nWHERE u.telegram_id = $1;",
"options": {
"queryReplacement": "={{ $('Build Toggle Response').item.json.telegram_id }}"
}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
-2608,
7824
],
"id": "ad7c564f-d756-4897-9cfc-dc904745f29c",
"name": "Refresh User Settings",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const user = $input.first().json;\nconst gender = user.gender;\nconst daysStreak = user.consecutive_perfect_days || 0;\nconst isPaused = user.is_paused || false;\nconst chatId = $('Build Toggle Response').item.json.chat_id;\nconst messageId = $('Build Toggle Response').item.json.message_id;\n\n// Build keyboard rows\nconst keyboard = [];\n\n// === PAUSE/RESUME TOGGLE ===\nconst pauseStatus = isPaused ? '\u25b6\ufe0f' : '\u23f8\ufe0f';\nconst pauseText = isPaused ? '\u0627\u0633\u062a\u0626\u0646\u0627\u0641 \u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a' : '\u0625\u064a\u0642\u0627\u0641 \u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a';\nkeyboard.push([{\n text: `${pauseStatus} ${pauseText}`,\n callback_data: 'settings|pause|toggle'\n}]);\n\n// === PROFILE SECTION (with gender icon) ===\nkeyboard.push([\n { text: '\ud83d\udccd \u0627\u0644\u0645\u0648\u0642\u0639', callback_data: 'settings|profile|location' },\n { text: '\u270f\ufe0f \u0627\u0644\u0627\u0633\u0645', callback_data: 'settings|profile|name' },\n { text: gender === 'male' ? '\ud83d\udc68' : '\ud83d\udc69', callback_data: 'settings|profile|gender' }\n]);\n\n// === PERIOD MODE FOR FEMALES ===\nif (gender === 'female') {\n const periodStatus = user.period_mode_active ? '\u2705' : '\u274c';\n keyboard.push([{\n text: `${periodStatus} \u0639\u0630\u0631 \u0634\u0631\u0639\u064a`,\n callback_data: 'settings|period|toggle'\n }]);\n}\n\n// === FEATURES SECTION ===\nconst azkarStatus = user.azkar_enabled ? '\u2705' : '\u274c';\nkeyboard.push([{\n text: `${azkarStatus} \u062a\u0646\u0628\u064a\u0647\u0627\u062a \u0627\u0644\u0623\u0630\u0643\u0627\u0631`,\n callback_data: 'settings|azkar|toggle'\n}]);\n\nconst sunnahStatus = user.sunnah_enabled ? '\u2705' : '\u274c';\nkeyboard.push([{\n text: `${sunnahStatus} \u062a\u062a\u0628\u0639 \u0635\u0644\u0648\u0627\u062a \u0627\u0644\u0633\u0646\u0629`,\n callback_data: 'settings|sunnah|toggle'\n}]);\n\nif (gender === 'male') {\n const masjidStatus = user.masjid_prayer_enabled ? '\u2705' : '\u274c';\n keyboard.push([{\n text: `${masjidStatus} \u062a\u062a\u0628\u0639 \u0635\u0644\u0627\u0629 \u0627\u0644\u062c\u0645\u0627\u0639\u0629`,\n callback_data: 'settings|masjid|toggle'\n }]);\n}\n\n// Close button\nkeyboard.push([{\n text: '\u274c \u0625\u063a\u0644\u0627\u0642',\n callback_data: 'settings|close'\n}]);\n\n// Build message\nconst cityName = user.city || '\u063a\u064a\u0631 \u0645\u062d\u062f\u062f';\nconst genderText = gender === 'male' ? '\u0630\u0643\u0631' : (gender === 'female' ? '\u0623\u0646\u062b\u0649' : '\u063a\u064a\u0631 \u0645\u062d\u062f\u062f');\n\nlet message = `\u2699\ufe0f *\u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a*\\n\\n`;\nmessage += `\ud83d\udc64 ${user.first_name} (${genderText})\\n`;\nmessage += `\ud83d\udccd ${cityName}\\n`;\nmessage += `\ud83d\udd25 \u0623\u064a\u0627\u0645 \u0645\u062a\u062a\u0627\u0644\u064a\u0629: ${daysStreak}\\n`;\n\nif (isPaused) {\n message += `\\n\u23f8\ufe0f *\u0627\u0644\u062a\u0646\u0628\u064a\u0647\u0627\u062a \u0645\u062a\u0648\u0642\u0641\u0629*\\n`;\n}\n\nif (gender === 'female' && user.period_mode_active) {\n message += `\\n\ud83c\udf38 *\u0648\u0636\u0639 \u0627\u0644\u0639\u0630\u0631 \u0627\u0644\u0634\u0631\u0639\u064a \u0645\u0641\u0639\u0651\u0644*\\n`;\n}\n\nmessage += `\\n\u0627\u0636\u063a\u0637 \u0639\u0644\u0649 \u0623\u064a \u062e\u064a\u0627\u0631 \u0644\u062a\u0641\u0639\u064a\u0644\u0647 \u0623\u0648 \u0625\u0644\u063a\u0627\u0626\u0647:`;\n\nreturn {\n json: {\n chat_id: chatId,\n message_id: messageId,\n message: message,\n keyboard: keyboard\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-2416,
7824
],
"id": "97992399-a02c-48d4-8db5-64bbb91e69f3",
"name": "Rebuild Settings Menu"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/editMessageText",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"chat_id\": {{ $json.chat_id }},\n \"message_id\": {{ $json.message_id }},\n \"text\": {{ JSON.stringify($json.message) }},\n \"parse_mode\": \"Markdown\",\n \"reply_markup\": {\n \"inline_keyboard\": {{ JSON.stringify($json.keyboard) }}\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-2224,
7824
],
"id": "6a8f44fc-813f-4655-99c7-b070051c4de5",
"name": "Edit Settings Message"
},
{
"parameters": {
"jsCode": "const feature = $('Parse Callback').item.json.action;\n\nconst levelRequirements = {\n 'focus': { level: 1, name: '\u0646\u0633\u0628\u0629 \u0627\u0644\u062e\u0634\u0648\u0639', requirement: '3 \u0623\u064a\u0627\u0645 \u0645\u062a\u062a\u0627\u0644\u064a\u0629' },\n 'sunnah': { level: 2, name: '\u0635\u0644\u0648\u0627\u062a \u0627\u0644\u0633\u0646\u0629', requirement: '7 \u0623\u064a\u0627\u0645 \u0645\u062a\u062a\u0627\u0644\u064a\u0629' },\n 'masjid': { level: 3, name: '\u0635\u0644\u0627\u0629 \u0627\u0644\u062c\u0645\u0627\u0639\u0629', requirement: '14 \u064a\u0648\u0645 \u0645\u062a\u062a\u0627\u0644\u064a' },\n 'quran': { level: 3, name: '\u0622\u064a\u0629 \u0642\u0631\u0622\u0646 \u064a\u0648\u0645\u064a\u0629', requirement: '14 \u064a\u0648\u0645 \u0645\u062a\u062a\u0627\u0644\u064a' },\n 'fasting': { level: 4, name: '\u0635\u064a\u0627\u0645 \u0623\u064a\u0627\u0645 \u0627\u0644\u0628\u064a\u0636', requirement: '21 \u064a\u0648\u0645 \u0645\u062a\u062a\u0627\u0644\u064a' },\n 'hadith': { level: 4, name: '\u062d\u062f\u064a\u062b \u064a\u0648\u0645\u064a', requirement: '21 \u064a\u0648\u0645 \u0645\u062a\u062a\u0627\u0644\u064a' },\n 'dua': { level: 5, name: '\u062f\u0639\u0627\u0621 \u064a\u0648\u0645\u064a', requirement: '30 \u064a\u0648\u0645 \u0645\u062a\u062a\u0627\u0644\u064a' }\n};\n\nconst info = levelRequirements[feature] || { level: 1, name: feature, requirement: '\u0627\u0644\u0627\u0644\u062a\u0632\u0627\u0645 \u0628\u0627\u0644\u0635\u0644\u0627\u0629' };\n\nconst message = `\ud83d\udd12 ${info.name} \u0645\u0642\u0641\u0644\u0629\\n\\n\u0627\u0644\u0645\u0637\u0644\u0648\u0628: ${info.requirement}\\n\\n\ud83d\udcaa \u0627\u0633\u062a\u0645\u0631 \u0641\u064a \u0627\u0644\u0627\u0644\u062a\u0632\u0627\u0645 \u0648\u0647\u062a\u0641\u062a\u062d!`;\n\nreturn {\n json: {\n callback_query_id: $('Parse Callback').item.json.callback_query_id,\n message: message\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-3360,
7808
],
"id": "e57a19de-03ef-478c-bd97-f1bf1a031691",
"name": "Build Locked Info"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "callback_query_id",
"value": "={{ $json.callback_query_id }}"
},
{
"name": "text",
"value": "={{ $json.message }}"
},
{
"name": "show_alert",
"value": "true"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-3168,
7808
],
"id": "c710c4d3-66c8-4cd3-9814-20d4e40f3626",
"name": "Show Locked Alert"
},
{
"parameters": {
"operation": "deleteMessage",
"chatId": "={{ $('Parse Callback').item.json.chat_id }}",
"messageId": "={{ $('Parse Callback').item.json.message_id }}"
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
-3360,
7936
],
"id": "823ee38a-6c74-4ac7-a487-ac1719632ebf",
"name": "Close Settings Menu",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"continueOnFail": true
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.N8N_WEBHOOK_URL }}/webhook/profile-callback",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ body: { telegram_id: $('Parse Callback').item.json.telegram_id, chat_id: $('Parse Callback').item.json.chat_id, message_id: $('Parse Callback').item.json.message_id, callback_query_id: $('Parse Callback').item.json.callback_query_id, callback_data: $('Parse Callback').item.json.callback_data } }) }}",
"options": {
"timeout": 30000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-3360,
8080
],
"id": "46cf84c3-1427-4057-96b4-51229cc79d85",
"name": "Forward to Profile Editor"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "callback_query_id",
"value": "={{ $('Parse Callback').item.json.callback_query_id }}"
},
{
"name": "text",
"value": "\u0647\u0630\u0627 \u0641\u0627\u0635\u0644 \u0641\u0642\u0637 \ud83d\ude0a"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-3360,
8224
],
"id": "29f12489-ab8c-43ac-8932-af92388204bf",
"name": "Answer NOOP"
},
{
"parameters": {
"content": "# Settings Callback Handler\nHandles toggle callbacks and profile editing from settings menu",
"height": 96,
"width": 500,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-4176,
7680
],
"id": "85071609-c58c-4f25-b1e4-03bb5f53f201",
"name": "Sticky Note1"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true }) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
-2736,
8096
],
"id": "df08dea7-11c0-4f48-98d8-2f9395df8d14",
"name": "Respond1"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"chat_id\": {{ $json.telegram_id }},\n \"text\": {{ JSON.stringify($json.message) }},\n \"parse_mode\": \"Markdown\",\n \"reply_markup\": {\n \"inline_keyboard\": {{ JSON.stringify($json.keyboard) }}\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-4624,
7808
],
"id": "f603af95-d58b-4d67-b83d-e968d14ffe9f",
"name": "HTTP Request"
},
{
"parameters": {
"content": "",
"height": 768,
"width": 4000,
"color": 2
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-5216,
7632
],
"id": "0c5e1087-0a27-43a6-aa36-7c272b7622e9",
"name": "Sticky Note27"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "e018928c-40eb-40f2-aa97-0b003d3987ae",
"leftValue": "={{ $json.feature }}",
"rightValue": "period",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-2800,
7664
],
"id": "63a8f6d3-be39-4825-ac45-2412e72ca8b5",
"name": "Is Period Toggle?"
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO daily_prayers (user_id, date, is_period_day)\nVALUES (\n $1,\n (CURRENT_TIMESTAMP AT TIME ZONE (SELECT timezone FROM users WHERE telegram_id = $1))::date,\n $2\n)\nON CONFLICT (user_id, date) DO UPDATE SET\n is_period_day = EXCLUDED.is_period_day;",
"options": {
"queryReplacement": "={{ $('Parse Callback').item.json.telegram_id }}, {{ $json.new_value }}"
}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
-2608,
7648
],
"id": "74050622-5b0b-4653-8109-dfc4b42eee56",
"name": "Update Period Day",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"content": "",
"height": 208,
"width": 192,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-4672,
7776
],
"id": "81bd441c-2a11-49ea-8229-c85215558c7c",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "",
"height": 176,
"width": 192,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-3216,
7792
],
"id": "c2e373c2-7917-4363-ba3d-121101cbc238",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "",
"height": 192,
"width": 192,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-3408,
8192
],
"id": "32c6d2fd-9bf4-4d66-9957-c4f6a90309dc",
"name": "Sticky Note5"
},
{
"parameters": {
"content": "",
"height": 208,
"width": 192,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2848,
7792
],
"id": "45c7804f-0fa9-4c65-8741-9356e4d0fc6d",
"name": "Sticky Note6"
},
{
"parameters": {
"content": "",
"height": 208,
"width": 192,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2272,
7792
],
"id": "a150d270-364f-40f9-87b0-c50d926b7abc",
"name": "Sticky Note7"
}
],
"connections": {
"Callback Router Webhook": {
"main": [
[
{
"node": "Parse Callback1",
"type": "main",
"index": 0
}
]
]
},
"Has Route?": {
"main": [
[
{
"node": "Forward to Handler",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Unknown",
"type": "main",
"index": 0
}
]
]
},
"Forward to Handler": {
"main": [
[
{
"node": "Respond6",
"type": "main",
"index": 0
}
]
]
},
"Log Unknown": {
"main": [
[
{
"node": "Respond6",
"type": "main",
"index": 0
}
]
]
},
"Parse Callback1": {
"main": [
[
{
"node": "Has Route?",
"type": "main",
"index": 0
}
]
]
},
"Settings Webhook": {
"main": [
[
{
"node": "Get User Settings",
"type": "main",
"index": 0
}
]
]
},
"Get User Settings": {
"main": [
[
{
"node": "Build Settings Menu",
"type": "main",
"index": 0
}
]
]
},
"Build Settings Menu": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Settings Callback Webhook": {
"main": [
[
{
"node": "Parse Callback",
"type": "main",
"index": 0
}
]
]
},
"Parse Callback": {
"main": [
[
{
"node": "Callback Router",
"type": "main",
"index": 0
}
]
]
},
"Callback Router": {
"main": [
[
{
"node": "Map Feature to Column",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Locked Info",
"type": "main",
"index": 0
}
],
[
{
"node": "Close Settings Menu",
"type": "main",
"index": 0
}
],
[
{
"node": "Forward to Profile Editor",
"type": "main",
"index": 0
}
],
[
{
"node": "Answer NOOP",
"type": "main",
"index": 0
}
]
]
},
"Map Feature to Column": {
"main": [
[
{
"node": "Toggle Setting",
"type": "main",
"index": 0
}
]
]
},
"Toggle Setting": {
"main": [
[
{
"node": "Build Toggle Response",
"type": "main",
"index": 0
}
]
]
},
"Build Toggle Response": {
"main": [
[
{
"node": "Answer Callback",
"type": "main",
"index": 0
},
{
"node": "Is Period Toggle?",
"type": "main",
"index": 0
}
]
]
},
"Answer Callback": {
"main": [
[
{
"node": "Refresh User Settings",
"type": "main",
"index": 0
}
]
]
},
"Refresh User Settings": {
"main": [
[
{
"node": "Rebuild Settings Menu",
"type": "main",
"index": 0
}
]
]
},
"Rebuild Settings Menu": {
"main": [
[
{
"node": "Edit Settings Message",
"type": "main",
"index": 0
}
]
]
},
"Edit Settings Message": {
"main": [
[
{
"node": "Respond1",
"type": "main",
"index": 0
}
]
]
},
"Build Locked Info": {
"main": [
[
{
"node": "Show Locked Alert",
"type": "main",
"index": 0
}
]
]
},
"Show Locked Alert": {
"main": [
[
{
"node": "Respond1",
"type": "main",
"index": 0
}
]
]
},
"Close Settings Menu": {
"main": [
[
{
"node": "Respond1",
"type": "main",
"index": 0
}
]
]
},
"Forward to Profile Editor": {
"main": [
[
{
"node": "Respond1",
"type": "main",
"index": 0
}
]
]
},
"Answer NOOP": {
"main": [
[
{
"node": "Respond1",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Respond",
"type": "main",
"index": 0
}
]
]
},
"Is Period Toggle?": {
"main": [
[
{
"node": "Update Period Day",
"type": "main",
"index": 0
}
]
]
}
},
"meta": {
"templateCredsSetupCompleted": true
}
}
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.
postgrestelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Settings. Uses httpRequest, postgres, telegram. Webhook trigger; 38 nodes.
Source: https://github.com/mustafatawfiq/hazem/blob/fba6bbcca492c550daa50b34b4f62fabcd1f1026/workflows/settings.json — 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.
Ban Claim Handler. Uses postgres, httpRequest, whatsApp, telegram. Webhook trigger; 20 nodes.
Ban Claim Handler. Uses postgres, httpRequest, whatsApp, telegram. Webhook trigger; 20 nodes.
Refund Handler. Uses postgres, minimax, httpRequest, whatsApp. Webhook trigger; 18 nodes.
Flujowhatsapp. Uses @aldinokemal2104/n8n-nodes-gowa, postgres, httpRequest. Webhook trigger; 65 nodes.
Pede Ai. Uses httpRequest, telegram, postgres, telegramTrigger. Event-driven trigger; 57 nodes.