How to use Telegram Bot for Contact Form
I have deleted my Facebook account for 3 months. Now I use Telegram as the main contact point. When building this “small universe”, I find out that I can use Telegram API for sending messages. A light bulb goes off in my head with an idea, using Telegram Bot for the Contact Form.
How it works
This feature may be too overkill for a simple contact form, I do it for the sake of learning and creating things. Let’s jump into building progress.
Telegram Settings
Bot
Creating a Telegram Bot is very simple. Telegram has another bot handling that process. Its name is BotFather. All I have to do is type some commands.

After creating Bot, I receive an authentication token for using the Bots API. It looks like 992219941:AAEEoFKKPN1qJWYZkVoujOFcHysITXa8uAY
. I’ll call <token>
from now on.
Group
According to the API documentation, I need a chat_id
of a group or a channel. The main reason is that a Bot cannot send direct messages to a User.
https://core.telegram.org/bots/api
chat_id
: Unique identifier for the target chat or username of the target channel (in the format@channelusername
)
When I have created a group, the first thing to do is give Administrator permission to the Bot.

To find chat_id
, I go to Group Type. A group is set to Private by default. It has a sharable link to join the group below, something like https://t.me/joinchat/<id>
.
At first, I’m quite sure that the <id>
here is chat_id
, but when I put it into the API call, it fails immediately. After a lot of attempts, the only way to get the format @channelusername
is to set Group Type to Public. So that I can have the group username
as purpose. For me, chat_id
will be @TheSmallUniverse
.

Telegram API
Now I already have <token>
and chat_id
, the next step is to connect the API. Following the documentation, Send Message API is the only API that I need.
Terminalcurl --location --request POST 'https://api.telegram.org/bot<token>/sendMessage' \ --header 'Content-Type: application/json' \ --data-raw '{ "chat_id": "@TheSmallUniverse", "text": "Hello Darkness, my old friend!" }'
And here is the response I get when running the command. There is a different detail, chat_id
has changed to an Integer -1001258275042
.
{ "ok": true, "result": { "message_id": 5, "from": { "id": 992219941, "is_bot": true, "first_name": "The Small Bot", "username": "TheSmallBot" }, "chat": { "id": -1001258275042, "title": "The Small Universe", "username": "TheSmallUniverse", "type": "supergroup" }, "date": 1578890703, "text": "Hello Darkness, my old friend!" } }
Contact Form
The configuration for Telegram is done. I need an UI to apply that functionality, and nothing better than a Contact Form.
User Interface
A meaningful message needs to have sender name, email and message content. As Telegram supports message formatting (Markdown & HTML), I come up with this interface.
On the client-side, I use Formik – a form validation library. When submitting the form, it calls an internal API, which is a simple serverless function.
Serverless Function
I use Next.js, which supports API Routes out of the box. If I don’t use Next.js, I could do this functionality with Zeit Serverless Functions or Netlify Functions.
The function looks like this:
messages.jsexport default async (req, res) => { const { name, message, email } = req.body if (!name || !message || !email) { res.status(400).json({ ok: false, status: 400, message: "Missing required fields", }) return } // https://core.telegram.org/bots/api#markdownv2-style const escapedEmail = email.replace(/_/g, "\\_") fetch(`https://api.telegram.org/bot${process.env.botToken}/sendMessage`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ chat_id: process.env.chatId, parse_mode: "Markdown", text: `“${message}”\n— ${name} <${escapedEmail}>`, }), }) .then((response) => response.json()) .then((data) => res.status(200).json(data)) .catch((err) => res.status(err.status).json(err)) }
During local development, I create a .env
file at the root of the project directory. It contains environment variables values.
.envCHAT_ID="@TheSmallUniverse" BOT_TOKEN="992219941:AAEEoFKKPN1qJWYZkVoujOFcHysITXa8uAY"
For production, I add these values to Now Secrets. They will be available at Build Time.
As I use Zeit Now service, all I have to do is config now.json
file.
now.json{ "version": 2, "name": "The Small Things", "build": { "env": { "CHAT_ID": "@thesmallthings.chat-id", "BOT_TOKEN": "@thesmallthings.bot-token" } } }
Then declare botToken
and chatId
in the next.config.js
as environment variables.
next.config.js// Use `dotenv` for local .env file require("dotenv").config() const nextConfig = { env: { chatId: process.env.CHAT_ID, botToken: process.env.BOT_TOKEN, }, }
Private Group
In my case, I don’t want to expose those messages for anyone in Telegram, so I set the group to Private.
At first, the Send Message API doesn’t accept @TheSmallUniverse
as chat_id
.
Because when moving group to Private, its sharable link has changed. So the old chat_id
won’t be available anymore.
Luckily, I have the Integer chat_id
from the previous API call.
{ "chat": { "id": -1001258275042, "title": "The Small Universe", "username": "TheSmallUniverse", "type": "supergroup" } }
Replace that value to .env
file, the function works as expected.
.envCHAT_ID="-1001258275042" BOT_TOKEN="992219941:AAEEoFKKPN1qJWYZkVoujOFcHysITXa8uAY"
But then, when I try to update Now Secrets for chat_id
, I get this error
Terminalnow secret add thesmallthings.chat-id -1001258275042 > Error! Invalid number of arguments. Usage: `now secret add <name> <value>`
That's because the secret value cannot contain the dash character. After searching for a while, I come across this solution.
At the root of the project directory, I create a chat-id.txt
file, its content is the chat_id
value.
Then update the command to use that file:
Terminalnow secret add -- thesmallthings.chat-id "`cat chat-id.txt`" > Success! Secret thesmallthings.chat-id added [762ms]
The cat chat-id.txt
takes the content of the chat-id.txt
file and pastes it into the command line for me.
And, what’s done is done. Now I have an helpful way to receive messages from anyone.