Viber Chatbot Mobile Development
Viber Public Account and Viber Bot are different products with different APIs. Public Account is for brands, managed through Viber Partners. Viber Bot is for developers, registered via developers.viber.com, suitable for automation. Most projects need the Bot API.
Registration and Setup
Bot creation happens via the Viber Admin Panel for developers. After creation, you receive an auth_token — used in every API request in the X-Viber-Auth-Token header. Webhook is set with a single POST:
import requests
def set_webhook(url: str, auth_token: str):
response = requests.post(
"https://chatapi.viber.com/pa/set_webhook",
headers={"X-Viber-Auth-Token": auth_token},
json={
"url": url,
"event_types": [
"delivered", "seen", "failed",
"subscribed", "unsubscribed",
"conversation_started", "message"
],
"send_name": True,
"send_photo": True
}
)
return response.json() # {"status": 0, "status_message": "ok"}
Viber confirms the webhook immediately in the response to set_webhook — no separate verification challenge like WhatsApp/Meta.
Message Types
Viber supports: text, picture, video, file, sticker, contact, url, location, and rich_media. rich_media is a custom carousel format with buttons, images, and titles:
def send_rich_media(receiver: str, auth_token: str, items: list):
rich_media = {
"Type": "rich_media",
"ButtonsGroupColumns": 6,
"ButtonsGroupRows": 7,
"BgColor": "#FFFFFF",
"Buttons": []
}
for item in items:
rich_media["Buttons"].extend([
{
"Columns": 6, "Rows": 3,
"ActionType": "open-url",
"ActionBody": item["url"],
"Image": item["image_url"]
},
{
"Columns": 6, "Rows": 1,
"Text": f"<b>{item['title']}</b>",
"ActionType": "none"
},
{
"Columns": 3, "Rows": 1,
"Text": "Learn More",
"ActionType": "open-url",
"ActionBody": item["url"],
"BgColor": "#2db5f5"
}
])
requests.post(
"https://chatapi.viber.com/pa/send_message",
headers={"X-Viber-Auth-Token": auth_token},
json={"receiver": receiver, "type": "rich_media", "rich_media": rich_media}
)
Rich Media is Viber-specific; Telegram has no equivalent. Excellent for product catalogs, news, and service cards.
Keyboard: Persistent and One-Time
Viber Keyboard is a custom on-screen keyboard. min_api_version: 1 for basic buttons:
keyboard = {
"Type": "keyboard",
"DefaultHeight": True,
"BgColor": "#FFFFFF",
"Buttons": [
{
"Columns": 3, "Rows": 1,
"Text": "Catalog",
"ActionType": "reply",
"ActionBody": "catalog",
"BgColor": "#f5f5f5"
},
{
"Columns": 3, "Rows": 1,
"Text": "Support",
"ActionType": "reply",
"ActionBody": "support",
"BgColor": "#f5f5f5"
}
]
}
The keyboard is sent with each message — it doesn't "stick" like in Telegram unless resent. Standard pattern: add the keyboard to every bot response.
conversation_started Event
conversation_started fires when a user opens the bot chat for the first time or via a deep link. This is the only moment to send a welcome message to an unsubscribed user. After this, the user must message the bot (subscribe) before it can send them messages.
Limitation: Viber doesn't allow bulk broadcasts to unsubscribed users — only those subscribed to the bot (the subscribed event).
Webhook Signature Verification
Every incoming request from Viber contains the X-Viber-Content-Signature header — HMAC-SHA256 of the request body with auth_token as the key:
import hmac, hashlib
def verify_viber_signature(body: bytes, signature: str, auth_token: str) -> bool:
expected = hmac.new(
auth_token.encode(),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Without this check, your webhook could accept forged messages from third parties.
Development Process
Registering bot in Viber Admin Panel. Setting up webhook with signature verification. Handling basic events: message, conversation_started, subscribed. Implementing Rich Media for catalogs/content. Dialog flows with state management (Redis FSM). Backend system integration.
Timeline Estimates
A simple information bot with keyboard and text replies — 1–2 weeks. A full-featured bot with Rich Media, FSM, CRM integration, and analytics — 4–7 weeks.







