Multichannel Bot Implementation (Telegram + WhatsApp + Viber) in Mobile Applications
Integrating a bot into one messenger is simple. Complexity starts when you need to cover Telegram, WhatsApp and Viber simultaneously — without turning codebase into three independent piles of logic. Main architectural task: unified business logic layer, isolate each platform's specifics behind adapter interface.
Why Three Bots is Not Three Times More Work, But Three Times More Errors
Each platform lives by its own rules. Telegram Bot API sends webhook synchronously and expects 200 OK response within 5 seconds — if backend hesitates, platform starts retrying, and bot receives duplicates. WhatsApp Business API (Meta Cloud API) works differently: webhook verification comes as GET request with hub.challenge, and if you don't answer with correct value, webhook simply won't register — silent error easy to miss.
Viber differs in rich media format: rich_media type with buttons works only when sending via send_message, not reply API. Developers migrating logic from Telegram (where inline keyboard attaches to any message) hit this on day one.
Separate story — attachment format. Telegram accepts multipart/form-data when sending file directly, WhatsApp requires uploading media first via POST /v1/media and getting media_id, only then send in message. Viber limits file size to 200 MB and supports strictly defined MIME types.
If all this logic scattered across one service without clear abstraction, maintaining it after half a year impossible.
Architecture: One Message Channel, Three Adapters
Correct approach — introduce BotAdapter interface with methods sendMessage, sendFile, parseIncoming. Each platform — its own implementation.
// Android (Kotlin) — adapter layer example
interface BotAdapter {
suspend fun sendMessage(chatId: String, text: String, buttons: List<BotButton>? = null)
suspend fun sendFile(chatId: String, fileUrl: String, mimeType: String)
fun parseIncoming(payload: String): BotMessage
}
class TelegramAdapter(private val token: String) : BotAdapter {
private val client = OkHttpClient()
override suspend fun sendMessage(chatId: String, text: String, buttons: List<BotButton>?) {
val body = buildTelegramPayload(chatId, text, buttons)
client.newCall(Request.Builder()
.url("https://api.telegram.org/bot$token/sendMessage")
.post(body).build()).execute()
}
// ...
}
On iOS same pattern — BotAdapter protocol and three struct implementations via URLSession. In Flutter convenient to use abstract class with dio under hood.
Business logic (command recognition, dialog FSM, database work) lives higher — it doesn't know where message came from.
Dialog State Management
For any non-trivial bot need finite state machine. Storing userState in memory — antipattern: on service restart all dialogs reset. In practice use Redis with TTL (e.g., 30 minutes inactivity resets session) or PostgreSQL table with updated_at.
State key — {platform}:{chatId}, allows one user to have independent dialogs in different messengers, which sometimes needed by business logic.
Mobile Application Specifics
If bot embedded not in server service but directly in mobile app — need WebSocket subscription or polling. For Telegram in mobile context this is getUpdates with long polling via BackgroundFetch (iOS) or WorkManager (Android). Can't keep permanent WebSocket for bot in iOS background — system kills process. Correct pattern: push notification from server wakes app, it does one getUpdates, processes queue and sleeps.
WhatsApp Cloud API in mobile app requires server proxy — can't call Meta API directly from mobile client (need verified business account on server side). This often surprises teams wanting "easy" integration.
Implementation Process
First — audit scenarios: what commands, need buttons/carousels, file exchange, payments (Telegram Payments vs WhatsApp Pay). This determines adapter complexity.
Next: FSM design, implement adapters in sequence (Telegram first — most mature API), integrate with main logic, load test webhooks.
Separate phase — monitoring: log incoming payloads with personal data masking, alerts on delivery_failed in Viber and failed webhook verifications.
Timeline Estimates
Bot in one messenger with basic commands — 3–5 days. Multichannel implementation with FSM, files, buttons and backend — 2–4 weeks. If need CRM or payment system integration — separate estimate after requirements analysis.







