> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Telegram bot dispatch and demo-account model

> How Devotel Orbit dispatches Telegram traffic through either your own BotFather bot or the shared demo bot, how the credentials repository resolves inbound updates and receipts back to an organization, and why every send writes a $0 ledger row on the free channel.

# Telegram bot dispatch and demo-account model

Telegram on Orbit is dispatched through exactly one of two assets: **your own BotFather bot** connected by pasting a token, or the **shared demo bot** Orbit operates for evaluation. This page defines how a dispatch picks between the two, how inbound updates and delivery receipts find their way back to your organization, and why a channel Telegram does not charge for still writes cost rows. The per-feature how-to lives on the [Telegram channel page](/channels/telegram); the cross-channel ladder vocabulary lives on [the channel test-account model](/concepts/channel-test-account-model). This page owns the Telegram-specific concepts.

## Dispatch: own bot or shared demo bot

Every Telegram send resolves one of two paths, decided by the same gate you meet as a 403:

* **Your own bot** — connected once by pasting the BotFather token into `POST /api/v1/telegram/connect-bot`. All Bot API features are available, dispatched under your bot's identity.
* **The shared demo bot** — available while you evaluate. You link one chat against the shared bot with `POST /api/v1/telegram/test/start-verify` (a five-minute deep-link token, rendered in the dashboard as a link and QR), and `POST /api/v1/telegram/test/send` dispatches curated demo content to that chat, bounded by a daily test-send allowance. When your organization also owns a bot, the same test/send endpoint dispatches through your own bot instead — the call shape never changes.

The gate classes are the cross-channel ones: the send-permitted gate opens on **either** an own bot **or** an active demo verification, and the asset-owner gate (bot identity mutations, payments, business connections, sticker packs) only opens on an own bot. Both classes are defined once on [the channel test-account model](/concepts/channel-test-account-model); Telegram implements them with the Bot API feature list.

## The demo pack, and what linking a chat unlocks

A verified demo account is not an empty channel. On verification, Orbit seeds a curated pack of demo content so the dashboard preview and the test send both have real material to work with:

* **Text templates** spanning the common transactional shapes — OTP, welcome, order status, appointment reminder, shipping update, payment receipt, feedback request, booking confirmation, account alert, back-in-stock — with `{{1}}`-style variables filled by sample values.
* **Inline keyboards** for conversational UX — a support menu, NPS collector, agent handoff, and an appointment time picker — rendered as real button matrices.
* **Reply keyboards** for the three Bot API request primitives (contact, location, group member) that inline buttons cannot express.
* **Polls, venues, Mini App, and streaming draft** — the remainder of the current Bot API surface presented as demo placeholders, so the preview shows what the paid surface will look like when you connect your own bot.

The whole pack is returned by `GET /api/v1/telegram/demo-content`, so your front end can render it without a Bot API round-trip. Demo content IDs follow a fixed `orbit_demo_*` prefix, which is how the demo gate filters curated material from operator-authored content on the test path.

## Resolving inbound updates back to your organization

Telegram webhook payloads do not carry the bot id — every bot's updates arrive on the same endpoint — so routing depends on the `X-Telegram-Bot-Api-Secret-Token` header Telegram echoes back from the secret registered at `setWebhook` time. The credentials repository resolves that header in ordered lanes:

1. **Per-organization bot credential row.** Each connected bot stores a per-row webhook secret; a match resolves the owning organization and refuses organizations that have been soft-deleted, so inbound into a retired tenant is rejected rather than routed.
2. **Shared demo-bot row.** The shared test bot is a single platform entry; a match authorizes the request, and tenant attribution then happens by verified chat id or by the linking token redeemed on `/start`.
3. **Derived platform secret.** A value derived from the platform secret — matching exactly what the platform registration passed to `setWebhook` — closes the loop between registration and verification without a second Secret.

Delivery receipts use the same first lane: the receipt endpoint resolves the bot by its webhook secret and returns a retryable failure if the lookup itself errors, so a database blip does not masquerade as a forged token. A missing or non-matching secret answers 401, and Orbit distinguishes a genuine mismatch from an infrastructure failure — a probe is logged and dropped; an outage is loud and retryable.

### The bot-credential lifecycle

One credential row per bot, kept for audit:

* **Connect** validates the token with a `getMe` call, stores the token encrypted, registers the webhook with its per-row secret, and marks the row active. A bot id can belong to exactly one organization at a time.
* **Disconnect** soft-retires the row (revoking the webhook) rather than deleting it — history of who owned a bot is preserved, and lookup lanes short-circuit retired rows cheaply.
* **Reconnect** reactivates a retired row in place, so re-pasting a bot token — by the same organization or a new one claiming a released bot — succeeds instead of colliding with the archived row.

Numeric Telegram bot ids exceed 32-bit range; they are handled as 64-bit values end-to-end so routing and ownership checks do not lose precision at the HTTP boundary.

## Cost model: ledger rows on a free channel

Telegram's Bot API is free at the provider level. Orbit still writes a \$0 cost row on every Telegram send, marked `free` for production traffic and `test` for demo-bot traffic:

* **Analytics stay complete.** The per-channel cost rollup aggregates message prices by channel; without an explicit row, Telegram volume would vanish from the chart and skew per-message-cost denominators low.
* **Demo traffic is metered.** Demo-tier rows let the platform account for the shared asset's operating cost, the same reason the WhatsApp demo tier is metered.
* **A wiring point for paid features.** When a paid Telegram surface such as Telegram Stars lands, the breakdown gains a unit-priced tier while the ledger shape, the aggregation, and the dashboard donut keep working unchanged.

The rollup endpoint `GET /api/v1/telegram/analytics/costs` splits demo vs free volume over a window and returns the totals with a free-tier disclaimer, so a future paid tier becomes a column in the same shape rather than a new integration.

## Cross-references

* [Telegram channel](/channels/telegram) — message shapes, keyboards, token handling, ownership disputes.
* [The channel test-account model](/concepts/channel-test-account-model) — the tester-to-producer ladder and the two gate classes shared across channels.
* [Telegram onboarding guide](/guides/telegram-onboarding) — the ordered how-to path from empty channel to production bot.
* [Sandbox, test mode, and the provisioning model](/concepts/provisioning-and-test-mode) — the orthogonal `dv_test_sk_*` simulation toggle.
