Telegram
Orbit’s Telegram channel wraps the Telegram Bot API so you can send and receive messages, photos, documents, inline keyboards, and callbacks from the same unified Messaging surface used for every other channel. Each Orbit organization can attach one bot; webhook delivery is automatic.Send a message
body field. Per-message options — the
send type (text (default), photo, video, document, location),
parse_mode, and keyboards — are passed under metadata, whose values are all
strings. Supply inline_keyboard (and reply_keyboard) as a JSON-stringified
button[][] array, exactly as shown above.
Response
Capabilities
- Text + media — text (with HTML / MarkdownV2 formatting), photo, video, document, and location. Set the send
typeinmetadata; a photo, video, or document send needsmediaUrl, and a location send needslatitude/longitude. - Inline + reply keyboards —
inline_keyboard,reply_keyboard, plusforce_replyandremove_keyboard. - Callbacks — inline-keyboard button presses arrive as Telegram
callback_queryupdates. Orbit ingests each press as an inbound message (the button’scallback_databecomes the messagebody), so it lands in the conversation timeline and fans out on the standardmessage.receivedwebhook — the same event as any other inbound Telegram message. There is no separatetelegram.callbackevent type to subscribe to. - Chat actions —
typing,upload_photo, etc., either via the API or auto-emitted by Orbit when a long-running send is in flight. - Edit + delete (Orbit-side only) —
PATCH /messages/:idedits thebodyand/orscheduled_atof a message that is still scheduled (not yet dispatched); once the message has been sent the edit returns409 MESSAGE_NOT_EDITABLE.DELETE /messages/:idsoft-deletes the Orbit message record and syncs that removal across your dashboards. Neither endpoint calls Telegram’seditMessageText/deleteMessage, so a message already delivered to the chat is not edited or removed in Telegram itself. - Bot commands + deep links — registered via the bot setup wizard;
/startdeep-links land on your conversation routing rules. - Webhook security — Telegram’s
secret_tokenheader is validated against the per-bot secret stored in Orbit’s encrypted credential vault.
Onboarding flow
- Talk to @BotFather and create a bot. Save the token it returns.
- From the dashboard, navigate to Channels → Telegram → Add bot and paste the token.
- Orbit auto-registers the webhook URL
https://api.orbit.devotel.io/api/v1/webhooks/inbound/telegramand rotates thesecret_tokenheader value. - Optional: configure the bot command list directly from the channel detail page.
Token handling — your responsibility
Telegram bot tokens are bearer credentials. Anyone who has the token can read every message sent to your bot, send messages on its behalf, and — until the token is revoked via BotFather — pose as your bot to your users. Orbit encrypts the token at rest with anenc:v1: envelope and never echoes it back through any API response, but the token’s safety upstream of Orbit (in your password manager, your laptop, your CI/CD variables, your screenshots) is yours to protect:
- Never commit a bot token to git, public or private. GitHub and GitLab both surface tokens to search; bots have scraped them in seconds.
- Never paste a token into a chat, ticket, screenshot, or screen-share. Use the dashboard paste field, which masks the value after submit.
- Rotate immediately via
/revokein BotFather if you believe a token has been exposed. Old tokens stop working the moment a new one is issued; reconnect in Orbit with the new value and the existing conversation history is preserved (we key history bybot_id, not by the token). - Scope each environment to its own bot. Use distinct BotFather bots for dev / staging / production so a leaked dev token doesn’t compromise customer conversations.
Ownership disputes
Orbit identifies a bot by itsbot_id (the numeric prefix of the token) and enforces a single-tenant claim: once an Orbit organization connects a bot, the same bot cannot be connected to a second Orbit organization until the first one disconnects. The dashboard surfaces TELEGRAM_BOT_ALREADY_CONNECTED (HTTP 409) when a second tenant attempts the same bot.
Connecting a bot to Orbit proves you have the bot’s token. It does NOT prove you are the BotFather owner of the bot. If a token leaks (see “Token handling” above) and a hostile actor claims it on their own Orbit tenant before you do, you will see a 409 on your own connect attempt — your bot is locked to someone else’s Orbit organization. Two recovery paths, in order of preference:
-
Revoke the token via BotFather (you, as the bot’s BotFather owner). Open @BotFather, select the bot, and run
/revoke. BotFather issues a new token; the leaked token immediately stops working. The hostile tenant’s webhook registration is now dead — Telegram refuses every send / receive against the old token. Once the hostile claim is functionally inert, contact Orbit support (see step 2) to release thebot_idclaim so you can connect with the new token. -
Open an ownership-dispute ticket with Orbit support. Email support@devotel.io with subject
Telegram bot ownership dispute — <bot_username>and include:- The bot’s
@usernameand numericbot_id(the digits before the colon in any token you’ve held). - Proof of BotFather ownership — a screenshot of the
/mybotslist in BotFather showing the bot under your Telegram account, OR a fresh token rotation timestamp from BotFather that we can correlate against Telegram’sgetMeresponse on the live token. - The Orbit organization you want the bot claim transferred to.
bot_idso you can connect from your own Orbit organization. Median response time is one business day; security-sensitive disputes are escalated to on-call. - The bot’s
Common errors
A failed send returns a JSON error envelope whoseerror.code is one of the
values below.
Blocked recipients
When a user blocks the bot, leaves a chat, deactivates their account, or the chat id is gone, Telegram returns a 403. Orbit does not raise an error for this — the message record is markedfailed with error_code set to
TELEGRAM_USER_BLOCKED. Treat that recipient as undeliverable: mark the contact
opted-out and skip future sends rather than retrying, because the condition is
permanent until the user re-engages the bot.