Skip to content

Guide

Send form submissions to Telegram

Some messages shouldn't wait for you to check email. Your phone buzzes; the record stays safe.

Last updated

Or skip the reading entirely.

Everything below is agent-work. Paste this to yours, then come back to a working form — you show up at the end to say "keep it."

Paste to your agent
Install the Postbag skill with `npx skills add faahim/postbag --skill postbag`, then use it to connect my Postbag form to a Telegram chat and prove a test delivery arrived.

Make yourself a bot

Telegram's rule is that software speaks through bots, and bots are minted by another bot. Open @BotFather in Telegram, send it /newbot, pick a display name and a username ending in bot. It hands back a token — that string is the bot's identity, so treat it like a password.

The whole conversation with @BotFather
/newbot
Site messages
mysitemessages_bot

Find your chat id

A bot can't message you until you've messaged it once — Telegram's politeness rule. Open your new bot, send it anything, then ask the API who wrote in. The number at chat.id is your chat id; for a group it's negative, and the bot needs to be a member.

One message to the bot, then:
curl "https://api.telegram.org/bot<your-bot-token>/getUpdates"

Tell Postbag about it

Create a Telegram Destination with the token and chat id. Postbag holds the token, formats each submission into a short readable note — not a wall of JSON on a phone screen — and owns the sending from here on.

Create the Destination
form_id="fm_YOUR_FORM_ID" # Copy yours from: npx postbag forms list
destination_json="$(curl --fail --silent --show-error -X POST https://postbag.dev/v1/destinations \
  -H "Authorization: Bearer pb_live_…" \
  -H "content-type: application/json" \
  -d '{
    "type": "telegram",
    "name": "My phone",
    "config": { "bot_token": "<your-bot-token>", "chat_id": "<your-chat-id>" }
  }')"
destination_id="$(printf '%s\n' "$destination_json" | jq -er '.id')"

printf 'Destination ID: %s\n' "$destination_id"

Prove it before it matters

Every Destination can be tested before a real message depends on it. This sends a test note through the actual bot to the actual chat — your phone should buzz within a breath or two.

Test the Destination
curl --fail --silent --show-error -X POST https://postbag.dev/v1/destinations/"$destination_id"/test \
  -H "Authorization: Bearer pb_live_…"

Route your Form to it

One Route ties the Form to the chat. From now on each new submission is stored first, then delivered to Telegram — and if Telegram has a moment, the message waits safely while Postbag retries. Prefer calm to buzzing? Switch the Route to a daily digest and get one tidy note instead.

Route Form → Telegram
route_body="$(jq -n --arg form_id "$form_id" --arg destination_id "$destination_id" \
  '{ form_id: $form_id, destination_id: $destination_id }')"

curl --fail --silent --show-error -X POST https://postbag.dev/v1/routes \
  -H "Authorization: Bearer pb_live_…" \
  -H "content-type: application/json" \
  -d "$route_body"

The parts that bite

The first message must be yours
Bots can't open a conversation. If getUpdates returns an empty list, you haven't messaged the bot yet — send it a hello and ask again.
Group ids go negative
A personal chat id is a positive number; a group's is negative, sometimes with a -100 prefix. Copy it exactly as getUpdates shows it, minus signs included.
One chat per Destination
A Destination points at one chat. Want your phone and a team group both notified? Two Destinations, two Routes — each keeps its own sending record.

Questions, answered

Is this a Zapier trick underneath?
No. Telegram is a native Destination — Postbag talks to Telegram's Bot API directly, and each delivery keeps its own retry count and outcome.
Can one form notify Telegram and my inbox?
Yes. Add an email Destination and a second Route. Each place hears about the same message independently.
What does the note look like?
The submission's fields as short labelled lines — built to be read on a phone, not decoded.
What if Telegram is unreachable?
The message is already stored. Postbag retries with growing pauses, and if attempts run out the delivery stays clearly marked for a manual retry.

Give the form job to your agent.

It can build, wire and test the form before you even sign up. Claim it when it's worth keeping.