The channel test-account model: shared test to BYO
Every interactive messaging channel on Orbit runs the same onboarding ladder: you send real traffic today through a shared test account that Orbit owns, prove your integration end to end, and then connect your own channel asset (a bot, a WhatsApp Business account, an RCS agent) to go to production. Telegram and WhatsApp ship this ladder as identical architecture — same per-channel state machine, same two gate classes, same capability contract — so once you understand one channel, you understand every channel that follows this model. This page defines the shared model; the channel pages carry the per-channel detail. The ladder is distinct fromdv_test_sk_* test mode: test mode decides whether a send is simulated (persisted, never dispatched, no provider reached), while the test account is a real delivery path — messages actually reach the provider under Devotel’s shared channel asset. Both exist so you can evaluate in the way that fits: simulation for integration shape, real delivery for end-to-end proof.
The tester-to-producer ladder, and why each channel’s step differs
The graduation step differs per channel for one reason: what it takes to own a production asset upstream.- Telegram is unregulated. The production asset is a BotFather bot, minted on demand in a chat with @BotFather. Graduation is pasting the token BotFather hands you into
POST /api/v1/telegram/connect-bot; Orbit validates the token with agetMecall and registers your webhook subscription immediately. There is no approval queue, no brand review, no waiting period — the token either resolves to a bot or it does not. - WhatsApp and RCS are regulated. The production asset is a Meta-approved WhatsApp Business Account (WABA) or a Google-approved RCS agent. Graduation goes through an approval cycle — Meta’s template and commerce policies on WhatsApp, Google’s agent verification on RCS — and takes hours to days. The shared test account exists precisely so that approval time is not dead integration time: you build and validate against the shared WABA while your own is pending.
The three-mode state machine
Your organization sits in exactly one mode per channel at any time. Telegram makes the modes explicit:
The transitions, and who advances each:
- Start verification — you call
POST /api/v1/telegram/test/start-verify, which mints a single-use linking token (five-minute TTL) and returns a deep link (https://t.me/<shared_bot>?start=verify_<token>) plus the same value to render as a QR code. Opening the link in Telegram and pressing Start redeems the token; Orbit’s inbound webhook binds that chat to your organization and advances the mode totest_active. - Paste a token — you call
POST /api/v1/telegram/connect-botwith the BotFather token. The token is validated againstgetMe, encrypted, and the webhook subscription registered. The mode becomesproduction. Production wins over test: when both exist, the state machine reportsproductionand the test block drops out of the response. - Disconnect —
POST /api/v1/telegram/test/disconnectclears the verified-chat link (back tonot_connected), andPOST /api/v1/telegram/disconnect-botrevokes the webhook registration and retires the BYO row.
The two gate classes
Every capability on these channels falls into one of two gate classes. This is the part of the model your code encounters as 403s.Send-permitted — reachable from both test and production
The send gate permits the call when either the organization owns a connected asset or the organization has an active test account. It answers one question: is this organization allowed to push traffic on this channel at all? Dashboards and preflight checks use it so they fan out without duplicating the test-mode allowance logic. Intest_active, per-send enforcement still applies underneath: sends go only to the verified chat, against the curated demo allowlist, bounded by a daily cap of 100 test sends per UTC day. Telegram and WhatsApp implement the send gate independently, but the contract — own asset or verified test account, both permitted — is identical.
Asset-owner-only — production only
The ownership gate rejects with403 FORBIDDEN unless the organization owns the channel asset. Telegram groups these Bot API features in it, because each one mutates the bot as an asset or operates the bot’s economy:
setMyCommandsbeyond the curated demo command set — the shared bot carries a demo command list you can exercise; redefining it is owner-only.setChatPhoto,setChatTitle,setChatDescription— chat identity mutations.- Payments:
sendInvoice,answerPreCheckoutQuery,answerShippingQuery. - Business connections (
getBusinessConnectionand the features bound to one). - Sticker-pack management (
createNewStickerSet,addStickerToSet,setStickerSetThumb). getMe/setMyNamemutations — anything that changes the bot identity itself.
403 FORBIDDEN with a connect-your-own message — on Telegram “Connect your own Telegram bot to use this feature”, on WhatsApp “Connect your WhatsApp Business account to use this feature”. Both are permanent, deterministic responses: connect the asset and the same call passes.
The shared-asset identity lock, and the $0 ledger rows
Two consequences of running on an asset Orbit owns: Identity mutations are a 403 even for an active test organization. The shared bot has one identity — its name, photo, command list, and sticker economy — serving every evaluating tenant. Iftest_active organizations could rename it or redefine its commands, one tenant’s experiment would be every tenant’s bot. So the ownership gate does not ask “are you allowed to send?” (the send gate does) but “do you own this asset?” — and on a test_active organization the answer is always no. Connect your own bot and the same calls pass.
Zero-cost rows exist on purpose. Telegram’s Bot API is free at the provider level, so every Telegram cost-ledger row is $0.00 — but the row is written anyway, marked tier: "test" when the send rode the shared bot. Three reasons:
- Cost analytics stay complete. The per-channel cost rollup aggregates message prices by channel; without an explicit $0 row, Telegram volume would vanish from the chart and skew per-message-cost denominators.
- Dev capacity is measurable. Test-tier rows let the platform account for the shared asset’s operating cost, the same reason the WhatsApp test tier is metered.
- Future paid features have a wiring point. When a paid Telegram surface lands (Telegram Stars), the tiers and consumers already exist.
What your code branches on
One read, one contract, no code change between test and production:GET /api/v1/<channel>/channel-stateis the single source of truth for where your organization sits on the ladder. On Telegram it reportsmode(not_connected,verifying,test_active,production), the shared bot username, the daily test-send counter and limit, the verified chat when test-linked, and the pending verification token whileverifying. The state read is deliberately degrade-safe: if an upstream availability fault hits it, Orbit returns the well-definednot_connectedempty state rather than a 5xx, so your dashboard card renders “Connect Telegram” instead of an error.- Branch on the returned
mode, never on your own record of what you connected. The per-mode capability matrix is exactly the gate table above:test_activegets send-permitted features to the verified chat;productiongets both gate classes. - The same endpoint routes differently per mode.
POST /api/v1/telegram/test/senddispatches: ontest_activeit sends via the shared bot to the verified chat and counts the daily cap; onproductionit sends through your own bot. Your integration’s send calls — dashboard or API — are identical before and after graduation. The only thing that changes between test and production is the answerschannel-stategives and which gates open.
Cross-references
- Telegram channel — message shapes, keyboards, token handling, ownership disputes.
- WhatsApp channel — templates, flows, catalog, Embedded Signup.
- Telegram onboarding guide — the ordered how-to path from empty channel to production bot.
- Sandbox, test mode, and the provisioning model — the orthogonal
dv_test_sk_*simulation toggle, and theTENANT_PROVISIONING503. - Verification lifecycle — how approval cycles on regulated channels progress.