Leave requests approved on Telegram

Employees fill in a leave form; the manager approves or rejects it with one tap on Telegram, and the employee gets an email.

Medium Saves ~4 hours/month ProductivityBy Flowngn team

Works with n8n · Make · Zapier

How it works

Trigger: Google Sheets — a new leave form response
  1. An employee submits the Google Form (name, email, dates, type, reason).
  2. The manager gets a Telegram message with Approve and Reject buttons.
  3. The decision is written back to the sheet.
  4. The employee gets an email with the decision.

Diagram

truefalseGNew leave requestGoogle Sheets TriggerTAsk managerTelegramGSave decisionGoogle Sheets⑂Approved?IfGEmail: approvedGmailGEmail: not approvedGmail
Trigger App Logic

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.

Workflow JSON
Show code (240 lines)
{
  "name": "Leave requests approved on Telegram (Flowngn)",
  "nodes": [
    {
      "parameters": {
        "content": "## Leave requests approved on Telegram\nEmployees fill in a leave form; the manager approves or rejects it with one tap on Telegram, and the employee gets an email.\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": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "Setup notes",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -420,
        -60
      ]
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Form Responses 1",
          "mode": "name"
        },
        "event": "rowAdded",
        "options": {}
      },
      "id": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "New leave request",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "operation": "sendAndWait",
        "chatId": "YOUR_MANAGER_CHAT_ID",
        "message": "=Leave request from {{ $json.Name }}\nType: {{ $json.Type }}\nFrom {{ $json.From }} to {{ $json.To }}\nReason: {{ $json.Reason || '-' }}",
        "approvalOptions": {
          "values": {
            "approvalType": "double",
            "approveLabel": "Approve",
            "disapproveLabel": "Reject"
          }
        },
        "options": {}
      },
      "id": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "Ask manager",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        300,
        0
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Form Responses 1",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Timestamp": "={{ $('New leave request').item.json.Timestamp }}",
            "Status": "={{ $json.data.approved ? 'Approved' : 'Rejected' }}"
          },
          "matchingColumns": [
            "Timestamp"
          ]
        },
        "options": {}
      },
      "id": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "Save decision",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        600,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $('Ask manager').item.json.data.approved }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "Approved?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        900,
        0
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $('New leave request').item.json.Email }}",
        "subject": "Your leave request is approved",
        "emailType": "text",
        "message": "=Hi {{ $('New leave request').item.json.Name }},\n\nYour {{ $('New leave request').item.json.Type }} leave from {{ $('New leave request').item.json.From }} to {{ $('New leave request').item.json.To }} is approved.\n\nYOUR_COMPANY HR",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "Email: approved",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1200,
        0
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $('New leave request').item.json.Email }}",
        "subject": "About your leave request",
        "emailType": "text",
        "message": "=Hi {{ $('New leave request').item.json.Name }},\n\nYour leave request from {{ $('New leave request').item.json.From }} to {{ $('New leave request').item.json.To }} wasn't approved this time. Your manager will talk to you about other dates.\n\nYOUR_COMPANY HR",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "310bce97-ca1c-4cff-a022-99304c58f5dc",
      "name": "Email: not approved",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1200,
        220
      ]
    }
  ],
  "connections": {
    "New leave request": {
      "main": [
        [
          {
            "node": "Ask manager",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask manager": {
      "main": [
        [
          {
            "node": "Save decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save decision": {
      "main": [
        [
          {
            "node": "Approved?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approved?": {
      "main": [
        [
          {
            "node": "Email: approved",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email: not approved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}

Open in the playground to edit →

Tips

  • Add a Google Calendar step on the approved branch to put the leave on the team calendar.

Related flows