πŸš€ More Vendrato tools: FunnelDupe β€’ GHL Utils
✈️

Telegram - Send Message with Custom Keyboard

n8n-nodes-base.httpRequest

Send Telegram messages with inline keyboards and callback buttons using Bot API. Create interactive bot experiences beyond basic messaging.

telegram bot interactive keyboard buttons
App Telegram
Category automation
Version 1.0.0
Author Community
Credentials Telegram Bot Token

πŸ’‘ Use Cases

πŸ“‹ Node Configuration

{
  "nodes": [
    {
      "parameters": {
        "content": "## ✈️ POST Telegram Message with Custom Keyboard\n\nSends Telegram messages with interactive inline keyboards and custom button layouts.\n\n**Required Parameters:**\n- `botToken`: Telegram Bot API token\n- `chatId`: Target chat or user ID\n- `text`: Message text content\n- `keyboard.buttons`: Array of button objects with text and callback_data or URL\n\n**Use Case:**\nCreate interactive Telegram bots with approval workflows, menu navigation, or quick action buttons. Supports both callback buttons and URL buttons for external links.",
        "height": 238,
        "width": 389,
        "color": 4
      },
      "id": "sticky-telegram-keyboard-001",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        96,
        332
      ],
      "meta": {
        "templateCredsSetupCompleted": true,
        "instanceId": "88a4b441e9a4af333af67be3c0ab8888b79ffa2aca1a09ed7a885e93b689b75f"
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $credentials.botToken }}/sendMessage",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"chat_id\": \"{{ $json.chatId }}\",\n  \"text\": \"{{ $json.message }}\",\n  \"parse_mode\": \"Markdown\",\n  \"reply_markup\": {\n    \"inline_keyboard\": [\n      [\n        {\n          \"text\": \"βœ… Approve\",\n          \"callback_data\": \"approve_{{ $json.requestId }}\"\n        },\n        {\n          \"text\": \"❌ Reject\",\n          \"callback_data\": \"reject_{{ $json.requestId }}\"\n        }\n      ],\n      [\n        {\n          \"text\": \"πŸ“Š View Details\",\n          \"url\": \"{{ $json.detailsUrl }}\"\n        }\n      ]\n    ]\n  }\n}",
        "options": {}
      },
      "id": "telegram-keyboard-001",
      "name": "Send Telegram Message with Keyboard",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        368,
        400
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "Telegram_Bot_Token",
          "name": "Telegram Bot Credentials"
        }
      }
    }
  ],
  "connections": {},
  "pinData": {}
}
[
  {
    "id": "1bdb0b70-a4e1-49e7-b9ea-914389596c2c",
    "meta": {
      "name": "API Call Node",
      "id": "api-call",
      "icon": {
        "svg": "",
        "type": "SVG"
      },
      "description": "## ✈️ POST Telegram Message with Custom Keyboard  Sends Telegram messages with interactive inline keyboards and custom button layouts."
    },
    "label": "Send Telegram Message with Keyboard",
    "dependencies": {
      "node-fetch": "3.3.2"
    },
    "script": "import fetch from \"node-fetch\";\nexport default async function apiCall({\n    url,\n    method,\n    contentType,\n    authorization,\n    body,\n    shouldAwait,\n    queryParams,\n    customHeaders\n}: NodeInputs, {\n    logging\n}: NodeScriptOptions) : NodeOutput  {\n    const headers = {\n        \"Content-Type\": contentType,\n        ...customHeaders\n    };\n    if (authorization) headers[\"Authorization\"] = authorization;\n\n    let queryParamsString = '';\n    if (queryParams) {\n        queryParamsString = '?' + new URLSearchParams(queryParams).toString();\n    }\n\n    const fetchOptions = {\n        method,\n        headers\n    };\n\n    if (method !== 'GET') {\n        fetchOptions.body = JSON.stringify(body);\n    }\n\n    const fetchPromise = fetch(url + queryParamsString, fetchOptions);\n\n    if (!shouldAwait) {\n        return {\n            data: null\n        };\n    }\n\n    const response = await fetchPromise;\n    const data = await response.json();\n    return {\n        status: response.status,\n        data\n    };\n}",
    "inputs": {
      "properties": {
        "method": {
          "type": "string",
          "description": "The HTTP method to use for the API call",
          "enum": [
            "GET",
            "POST",
            "PUT",
            "DELETE",
            "PATCH"
          ],
          "default": "POST",
          "title": "HTTP Method",
          "buildship": {
            "options": [
              {
                "label": "GET",
                "value": "GET"
              },
              {
                "value": "POST",
                "label": "POST"
              },
              {
                "value": "PUT",
                "label": "PUT"
              },
              {
                "label": "DELETE",
                "value": "DELETE"
              },
              {
                "label": "PATCH",
                "value": "PATCH"
              }
            ],
            "index": 0,
            "sensitive": false
          }
        },
        "url": {
          "description": "The URL of the API endpoint",
          "title": "URL",
          "type": "string",
          "buildship": {
            "index": 1
          }
        },
        "authorization": {
          "description": "The authorization header for the API call, if required (e.g., Bearer or Basic token)",
          "type": "string",
          "title": "Authorization",
          "buildship": {
            "sensitive": true,
            "index": 2
          }
        },
        "queryParams": {
          "default": {},
          "description": "The query parameters for the API call",
          "type": "object",
          "title": "Query Parameters",
          "buildship": {
            "index": 3,
            "sensitive": false
          }
        },
        "body": {
          "type": "object",
          "buildship": {
            "index": 4
          },
          "description": "The body to send with the API call",
          "title": "Body"
        },
        "contentType": {
          "enum": [
            "application/json",
            "application/x-www-form-urlencoded",
            "multipart/form-data",
            "text/plain"
          ],
          "description": "The content type of the API call",
          "title": "Content Type",
          "buildship": {
            "index": 5,
            "options": [
              {
                "label": "application/json",
                "value": "application/json"
              },
              {
                "value": "application/x-www-form-urlencoded",
                "label": "application/x-www-form-urlencoded"
              },
              {
                "label": "multipart/form-data",
                "value": "multipart/form-data"
              },
              {
                "label": "text/plain",
                "value": "text/plain"
              }
            ]
          },
          "type": "string"
        },
        "shouldAwait": {
          "description": "Whether to wait for the request to complete or not",
          "title": "Await?",
          "type": "boolean",
          "buildship": {
            "sensitive": false,
            "index": 6
          }
        },
        "customHeaders": {
          "type": "object",
          "description": "Additional custom headers for the API call",
          "title": "Custom Headers",
          "buildship": {
            "index": 7,
            "sensitive": false
          }
        }
      },
      "type": "object",
      "required": [
        "url",
        "shouldAwait",
        "method"
      ]
    },
    "integrations": [],
    "name": "API Call Node",
    "output": {
      "buildship": {},
      "properties": {
        "status": {
          "buildship": {
            "index": 0
          },
          "type": "number",
          "description": "The HTTP status of the API response",
          "title": "Status"
        },
        "data": {
          "buildship": {
            "index": 1
          },
          "title": "Data",
          "type": "object",
          "description": "The data object from the API response"
        }
      },
      "type": "object"
    },
    "isCollapsed": false,
    "type": "script",
    "values": {
      "method": "POST",
      "url": {
        "_$expression_": "`https://api.telegram.org/bot{{ $credentials.botToken }}/sendMessage`",
        "type": "javascript",
        "hasErrors": false
      },
      "authorization": {
        "_$expression_": "`Bearer ${(await getSecret(\"ANONYMIZED_SECRET\"))}`",
        "type": "javascript",
        "hasErrors": false
      },
      "queryParams": {},
      "body": {
        "_$expression_": "{\n  \"chat_id\": ctx?.[\"root\"]?.[\"inputs\"]?.[\"body\"].chatId,\n  \"text\": ctx?.[\"root\"]?.[\"inputs\"]?.[\"body\"].message,\n  \"parse_mode\": \"Markdown\",\n  \"reply_markup\": {\n    \"inline_keyboard\": [\n      [\n        {\n          \"text\": \"βœ… Approve\",\n          \"callback_data\": \"approve_ctx?.[\"root\"]?.[\"inputs\"]?.[\"body\"].requestId\n        },\n        {\n          \"text\": \"❌ Reject\",\n          \"callback_data\": \"reject_ctx?.[\"root\"]?.[\"inputs\"]?.[\"body\"].requestId\n        }\n      ],\n      [\n        {\n          \"text\": \"πŸ“Š View Details\",\n          \"url\": ctx?.[\"root\"]?.[\"inputs\"]?.[\"body\"].detailsUrl\n        }\n      ]\n    ]\n  }\n}",
        "type": "javascript",
        "hasErrors": false
      },
      "contentType": "application/json",
      "shouldAwait": true,
      "customHeaders": {}
    }
  }
]
{
  "subflows": [
    {
      "flow": [
        {
          "id": 486,
          "module": "http:ActionSendDataBasicAuth",
          "version": 3,
          "parameters": {
            "key": "ANONYMIZED_CREDENTIALS",
            "handleErrors": false,
            "useNewZLibDeCompress": true
          },
          "mapper": {
            "ca": "",
            "qs": [],
            "url": "https://api.telegram.org/bot{{ $credentials.botToken }}/sendMessage",
            "data": "{\n  \"chat_id\": {{1.chatId}},\n  \"text\": {{1.message}},\n  \"parse_mode\": \"Markdown\",\n  \"reply_markup\": {\n    \"inline_keyboard\": [\n      [\n        {\n          \"text\": \"βœ… Approve\",\n          \"callback_data\": \"approve_{{1.requestId}}\n        },\n        {\n          \"text\": \"❌ Reject\",\n          \"callback_data\": \"reject_{{1.requestId}}\n        }\n      ],\n      [\n        {\n          \"text\": \"πŸ“Š View Details\",\n          \"url\": {{1.detailsUrl}}\n        }\n      ]\n    ]\n  }\n}",
            "gzip": true,
            "method": "post",
            "headers": [
              {
                "name": "Authorization",
                "value": "Bearer {{ANONYMIZED_TOKEN}}"
              }
            ],
            "timeout": "",
            "useMtls": false,
            "bodyType": "raw",
            "contentType": "application/json",
            "serializeUrl": false,
            "shareCookies": false,
            "parseResponse": true,
            "followRedirect": true,
            "useQuerystring": false,
            "followAllRedirects": false,
            "rejectUnauthorized": true
          },
          "metadata": {
            "designer": {
              "x": 300,
              "y": 300,
              "name": "POST Telegram Message with Custom Keyboard"
            },
            "restore": {
              "expect": {
                "qs": {
                  "mode": "chose",
                  "items": []
                },
                "method": {
                  "mode": "chose",
                  "label": "POST"
                },
                "headers": {
                  "mode": "chose",
                  "items": [
                    null
                  ]
                },
                "bodyType": {
                  "label": "Raw"
                },
                "contentType": {
                  "label": "JSON (application/json)"
                }
              },
              "parameters": {
                "key": {
                  "label": "ANONYMIZED_CREDENTIALS"
                }
              }
            },
            "parameters": [
              {
                "name": "key",
                "type": "keychain:basicauth",
                "label": "Credentials",
                "required": true
              },
              {
                "name": "handleErrors",
                "type": "boolean",
                "label": "Evaluate all states as errors (except for 2xx and 3xx )",
                "required": true
              },
              {
                "name": "useNewZLibDeCompress",
                "type": "hidden"
              }
            ],
            "expect": [
              {
                "name": "url",
                "type": "url",
                "label": "URL",
                "required": true
              },
              {
                "name": "serializeUrl",
                "type": "boolean",
                "label": "Serialize URL",
                "required": true
              },
              {
                "name": "method",
                "type": "select",
                "label": "Method",
                "required": true,
                "validate": {
                  "enum": [
                    "get",
                    "head",
                    "post",
                    "put",
                    "patch",
                    "delete",
                    "options"
                  ]
                }
              },
              {
                "name": "headers",
                "spec": [
                  {
                    "name": "name",
                    "type": "text",
                    "label": "Name",
                    "required": true
                  },
                  {
                    "name": "value",
                    "type": "text",
                    "label": "Value"
                  }
                ],
                "type": "array",
                "label": "Headers"
              },
              {
                "name": "qs",
                "spec": [
                  {
                    "name": "name",
                    "type": "text",
                    "label": "Name",
                    "required": true
                  },
                  {
                    "name": "value",
                    "type": "text",
                    "label": "Value"
                  }
                ],
                "type": "array",
                "label": "Query String"
              },
              {
                "name": "bodyType",
                "type": "select",
                "label": "Body type",
                "validate": {
                  "enum": [
                    "raw",
                    "x_www_form_urlencoded",
                    "multipart_form_data"
                  ]
                }
              },
              {
                "name": "parseResponse",
                "type": "boolean",
                "label": "Parse response",
                "required": true
              },
              {
                "name": "contentType",
                "type": "select",
                "label": "Content type",
                "validate": {
                  "enum": [
                    "text/plain",
                    "application/json",
                    "application/xml",
                    "text/xml",
                    "text/html",
                    "custom"
                  ]
                }
              },
              {
                "name": "data",
                "type": "buffer",
                "label": "Request content"
              }
            ]
          }
        }
      ]
    }
  ],
  "metadata": {
    "version": 1
  }
}
← Browse all nodes