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 →
{
"name": "03_admin_refund_handler",
"nodes": [
{
"parameters": {
"content": "## Spending",
"height": 208,
"width": 288,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"typeVersion": 1,
"id": "05ae9c8e-bd93-4d58-83ff-8c7af8c90073",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Earning",
"height": 240,
"width": 448,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
272
],
"typeVersion": 1,
"id": "cfb0d8c2-77ea-4862-b091-8cfd2043c14e",
"name": "Sticky Note3"
},
{
"parameters": {
"updates": [
"callback_query"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
-1248,
320
],
"id": "7938bf69-c089-4d51-87c1-8565a3681cec",
"name": "Admin Button Click (Trigger)",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Get data from the clicked button\nconst item = items[0].json;\nconst buttonData = item.data || (item.callback_query && item.callback_query.data);\n\nif (!buttonData) throw new Error(\"No callback data found in button\");\n\n// Data format: action|phone|amount1|amount2\nconst parts = buttonData.split('|');\n\nreturn {\n json: {\n action: parts[0], // 'undo_add' or 'undo_mix'\n phone: parts[1],\n amount1: parseInt(parts[2]), // Primary amount\n amount2: parseInt(parts[3]) || 0 // Secondary amount (for mixed payments)\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1040,
320
],
"id": "ab6a0406-1fbf-491d-8be4-6af90e464cfc",
"name": "Parse Button Data"
},
{
"parameters": {
"method": "POST",
"url": "https://api-ru.iiko.services/api/1/access_token",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "apiLogin",
"value": "REPLACE_WITH_SECRET"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-800,
320
],
"id": "05edfcf3-1db1-4d7b-a063-7dd5ea196a09",
"name": "iiko Auth (Get Token)",
"retryOnFail": true,
"waitBetweenTries": 3000
},
{
"parameters": {
"method": "POST",
"url": "https://api-ru.iiko.services/api/1/loyalty/iiko/customer/info",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('iiko Auth (Get Token)').item.json.token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"organizationId\": \"org_id\",\n \"phone\": \"+7{{ $('Parse Button Data').item.json.phone.toString().replace(/\\D/g, '').slice(-10) }}\",\n \"type\": \"phone\"\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-560,
320
],
"id": "af43df8f-7fff-4a2b-9860-9446c1e9881c",
"name": "Fetch Customer Wallet",
"retryOnFail": true,
"waitBetweenTries": 3000
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $('Parse Button Data').item.json.action }}",
"rightValue": "undo_add",
"operator": {
"type": "string",
"operation": "equals"
},
"id": "0c3ffd14-d854-4681-8527-951873a1055a"
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "undo_add"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "f42ca719-44de-4cb8-993b-e412fa97b0c1",
"leftValue": "={{ $('Parse Button Data').item.json.action }}",
"rightValue": "undo_mix",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "undo_mix"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.3,
"position": [
-320,
320
],
"id": "c948fc1f-a45c-49fd-a4f1-ede6c46a3070",
"name": "Router: Refund Type"
},
{
"parameters": {
"method": "POST",
"url": "https://api-ru.iiko.services/api/1/loyalty/iiko/customer/wallet/chargeoff",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('iiko Auth (Get Token)').item.json.token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"organizationId\": \"org_id\",\n \"customerId\": \"{{ $json.id }}\",\n \"walletId\": \"my_id\",\n \"sum\": {{ $('Parse Button Data').item.json.amount1 }},\n \"comment\": \"Order Cancelled (Revert Accrual)\"\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
80,
48
],
"id": "2060c689-e30d-4379-aac2-9aca6a95a0ea",
"name": "Revoke Accrued Points",
"alwaysOutputData": true,
"retryOnFail": true,
"waitBetweenTries": 3000
},
{
"parameters": {
"method": "POST",
"url": "https://api-ru.iiko.services/api/1/loyalty/iiko/customer/wallet/topup",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('iiko Auth (Get Token)').item.json.token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"organizationId\": \"org_id\",\n \"customerId\": \"{{ $json.id }}\",\n \"walletId\": \"my_id\",\n \"sum\": {{ $('Parse Button Data').item.json.amount1 }},\n \"comment\": \"Refund Spent Points (Order Cancelled)\"\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-32,
336
],
"id": "b868ff11-ae7d-4aba-897e-95f232664b53",
"name": "Refund: Return Spent Points",
"retryOnFail": true,
"waitBetweenTries": 3000
},
{
"parameters": {
"resource": "callback",
"queryId": "={{ $('Admin Button Click (Trigger)').item.json.callback_query.id }}",
"additionalFields": {
"text": "\u2705 The bonuses reverted to the opposite state"
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
480,
336
],
"id": "d770c5e6-a42d-4f3c-a779-ac154220929a",
"name": "Stop Button Loading",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "editMessageText",
"chatId": "={{ $('Admin Button Click (Trigger)').item.json.callback_query.message.chat.id }}",
"messageId": "={{ $('Admin Button Click (Trigger)').item.json.callback_query.message.message_id }}",
"text": "=\u274c <b>\u0414\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043a\u0430\u0437 \u043e\u0442\u043c\u0435\u043d\u0435\u043d</b> \n(\u041d\u0430\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0431\u043e\u043d\u0443\u0441\u044b \u0431\u044b\u043b\u0438 \u0441\u043f\u0438\u0441\u0430\u043d\u044b/\u043d\u0430\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u043e\u0431\u0440\u0430\u0442\u043d\u043e)\n\n<b>\u0418\u0421\u0422\u041e\u0420\u0418\u042f \u0417\u0410\u041a\u0410\u0417\u0410:</b>\n{{ $('Admin Button Click (Trigger)').item.json.callback_query.message.text }}",
"additionalFields": {
"parse_mode": "HTML"
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
688,
336
],
"id": "6dbd2fe5-1897-4ac2-9b87-b514c14b7afe",
"name": "Update Admin Message (RU)",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"content": "**Admin Refund Handler**\nTriggered when Admin clicks \"Cancel Order\" in Telegram.\n1. **Parse:** Decodes hidden data in the button (Phone, Amounts, Action type).\n2. **Auth:** Connects to iikoCard.\n3. **Route:** Determines refund type:\n * **Simple:** Just revoke points earned.\n * **Mixed:** Return spent points AND revoke points earned on cash part.\n4. **Update:** Changes message status to \"Cancelled\".",
"height": 288,
"width": 320
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-1664,
240
],
"typeVersion": 1,
"id": "873a0b51-a5c6-4609-8f74-75c49aab31b7",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "**Refund Logic Router**\n* `undo_add`: Cancel accrual only (Customer didn't spend points).\n* `undo_mix`: Full reversal (Customer spent points + paid remaining cash).",
"height": 176
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-384,
112
],
"typeVersion": 1,
"id": "0b8126fa-5d63-4161-8449-02cbcc907342",
"name": "Sticky Note2"
},
{
"parameters": {
"method": "POST",
"url": "https://api-ru.iiko.services/api/1/loyalty/iiko/customer/wallet/chargeoff",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('iiko Auth (Get Token)').item.json.token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"organizationId\": \"org_id\",\n \"customerId\": \"{{ $('Router: Refund Type').item.json.id }}\",\n \"walletId\": \"my_id\",\n \"sum\": {{ $('Parse Button Data').item.json.amount2 }},\n \"comment\": \"Revoke Accrual (Order Cancelled)\"\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
192,
336
],
"id": "8309dee9-5664-4d80-bbc5-7922dacc02fe",
"name": "Revoke Cash-Part Points",
"retryOnFail": true,
"waitBetweenTries": 3000
}
],
"connections": {
"Admin Button Click (Trigger)": {
"main": [
[
{
"node": "Parse Button Data",
"type": "main",
"index": 0
}
]
]
},
"Parse Button Data": {
"main": [
[
{
"node": "iiko Auth (Get Token)",
"type": "main",
"index": 0
}
]
]
},
"iiko Auth (Get Token)": {
"main": [
[
{
"node": "Fetch Customer Wallet",
"type": "main",
"index": 0
}
]
]
},
"Fetch Customer Wallet": {
"main": [
[
{
"node": "Router: Refund Type",
"type": "main",
"index": 0
}
]
]
},
"Router: Refund Type": {
"main": [
[
{
"node": "Revoke Accrued Points",
"type": "main",
"index": 0
}
],
[
{
"node": "Refund: Return Spent Points",
"type": "main",
"index": 0
}
]
]
},
"Revoke Accrued Points": {
"main": [
[
{
"node": "Stop Button Loading",
"type": "main",
"index": 0
}
]
]
},
"Refund: Return Spent Points": {
"main": [
[
{
"node": "Revoke Cash-Part Points",
"type": "main",
"index": 0
}
]
]
},
"Stop Button Loading": {
"main": [
[
{
"node": "Update Admin Message (RU)",
"type": "main",
"index": 0
}
]
]
},
"Revoke Cash-Part Points": {
"main": [
[
{
"node": "Stop Button Loading",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"availableInMCP": false,
"timeSavedMode": "fixed",
"timezone": "Asia/Almaty",
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": "hqRcKQkYO4KNl7CpVzjbg"
},
"versionId": "7e4467d2-02ab-4356-91f6-c4f751339fec",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "2G2CemAcy0HxpbjE_CMQo",
"tags": []
}
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
About this workflow
03_admin_refund_handler. Uses stickyNote, telegramTrigger, httpRequest, telegram. Event-driven trigger; 14 nodes.
Source: https://github.com/gulnaz-bakinova/n8n-automation-integrations-showcase/blob/main/03_admin_refund_handler.json — original creator credit. Request a take-down →