Connect a Telegram bot to Dairo and send and receive Telegram messages through the same inbox, mailbox, and send call as email.
Connect a Telegram bot and it becomes a Dairo inbox. Messages people send the bot arrive in your mailbox as structured messages, and your agent answers with the same send call it already uses for email. Setup is one API call and a one-time verification code.
Telegram rides the same model as every Dairo channel: the
bot is an inbox with channel: "telegram", inbound messages land in the
mailbox, and message.* webhooks fire as usual. The only channel-specific step
is the connect.
Connect a bot
Create the bot
In Telegram, open @BotFather, send /newbot, and
follow the prompts. BotFather returns a bot token that looks like
123456789:AAE.... Keep it secret — anyone who has it can control the bot.
Connect it to Dairo
Create the inbox by passing the token to POST /v1/inboxes. There is no domain
or address to set up — a Telegram inbox has no email identity.
Dairo validates the token with Telegram — an invalid token is a 400 — then
creates the inbox and returns a six-character verification code:
Verify you own the bot
Open connectUrl — it opens the bot in Telegram and tapping Start sends
the code for you — or open the bot yourself and send the code as a message. The
bot confirms the connection in the chat, and that conversation becomes the
inbox's home chat.
Until the code arrives, the bot answers every message with a prompt for the code, and nothing is stored in your mailbox.
Connecting the same bot a second time returns the existing inbox instead of creating a duplicate.
Receive messages
Every message sent to the bot lands in your mailbox with
channel: "telegram", readable with the same list and get calls as any other
message.
Each entry in data carries the sender and the reply coordinates:
channelMetadata field | What it is |
|---|---|
chatId | The conversation the message came from. Echo it back as telegram:{chatId} to reply. |
telegramMessageId | Telegram's id for this message. |
updateId | Telegram's delivery id, for your own dedup if you want it. |
fromUsername | The sender's public username, when they have one. |
The sender's from.address is always the chat, telegram:{chatId} — the value you
reply to — never their @username, because a bot cannot message a user by username.
Three things happen on arrival without any code on your side:
- Each inbound message fires the
message.receivedwebhook, so your agent can react instead of polling. - Photos, documents, video, audio, and voice notes are downloaded and attached to the message as first-class attachments; a caption becomes the text body.
- The bot answers a fixed set of built-in commands itself —
/start,/help,/status,/usage,/whoami. Those never reach your mailbox; every other command and message does.
Send and reply
Send with the same POST /v1/messages call as email: point inboxId at the
Telegram inbox and put a Telegram recipient in to.
The response comes back with status: "sent" and channel: "telegram", and
the send appears in GET /v1/messages like any other outbound message.
A Telegram send goes to exactly one chat. Put at most one Telegram target in to:
a second one, or any cc or bcc, is a 400 rather than a silently dropped
recipient.
to entry | Delivers to |
|---|---|
telegram:{chatId} | That chat. Echo channelMetadata.chatId from the message you are answering. |
@username or telegram:@username | A public username — another bot, or a channel the bot can post to. |
| Any other recipient (a regular address) | The home chat — the conversation that sent the verification code. |
A send to an unverified inbox that names no @username target is a 422: the
bot has no home chat until the code is verified. Scheduled sends (sendAt) are
not supported on the Telegram channel and return a 400.
For formatted output — headings, lists, tables, code blocks, media captions —
send an html body instead of text and Telegram renders it as a rich
message. The rich messages guide covers
the supported markup.
Buttons, edits, and reactions
Telegram is more than text in, text out. On the same surface your agent can:
- Attach inline buttons — pass
buttons, an array of rows, each row an array of{text, url}link buttons or{text, callback}action buttons. - Handle a tap — a callback tap arrives as a normal inbound message and
fires the
message.receivedwebhook, so your agent branches on the choice. The event stream also records amessage.button.tappedevent with the button's label and callback value. - Edit a sent message —
POST /v1/messages/{messageId}/editreplaces the text, HTML, or keyboard in place. - React —
POST /v1/messages/{messageId}/reactsets the bot's emoji reaction on a message you sent or received;/unreactclears it. - Send native types — a
telegramobject on the send carries exactly one oflocation,venue,contact,poll,dice,sticker,videoNote, orvoice(a synthesized voice note from text).
Button shapes, tap handling, editing, reactions, media, voice, and bot-to-bot messaging are covered end to end in the Telegram interactivity guide.
Behavior and limits
- One bot, one inbox. Reconnecting the same bot returns the same inbox, and a
bot that is already verified comes back
active, with no new verification code. - Plan limit. A Telegram inbox counts against your plan's inbox limit like any
other inbox; connecting a bot over the limit is a
429whose message names the inbox plan limit (the code is currentlyrate_limited, see plan limits on resource counts). - Scopes. Reading rides
messages:read; sending, editing, and reacting ridemessages:send; connecting a bot ridesinboxes:write. - Synthetic address. A Telegram inbox has no email identity. Its
addressfield carries an internal handle of the formtg-{botId}@telegram.dairo.localused for routing and filtering — it is not deliverable email. - Quota. Each Telegram send counts as one message against your monthly
message quota; a send over quota returns a
429.
Related
- Slack — the same receive-and-reply model, installed into your customers' workspaces instead of connected with a token.
- Build a support inbox agent — a worked agent over the unified inbox.