Viber API Documentation7.3.0

Docs / All

Viber Node.JS Bot API

Use this library to develop a bot for the Viber platform. The library is available on GitHub as well as a package on npm.

Important notes for bot developers: Please note that since 5.02.24, Viber bots can only be created on commercial terms. Before you start developing your bot in Viber please check how to apply for a bot creation here.

License

This library is released under the terms of the Apache 2.0 license. See License for more information.

Library Prerequisites

  1. Node >= 5.0.0
  2. An Active Viber account on a platform which supports bots (iOS/Android). This account will be set as the account administrator during the account creation process.
  3. Active bot.
  4. Account authentication token - unique account identifier used to validate your account in all API requests. Once your account is created your authentication token will appear in the account’s “edit info” screen (for admins only). Each request posted to Viber by the account will need to contain the token.
  5. Webhook - Please use a server endpoint URL that supports HTTPS. If you deploy on your own custom server, you’ll need a trusted (ca.pem) certificate, not self-signed. Read our blog post on how to test your bot locally.

Installation

This library is released on npm.

npm

Install with npm install viber-bot --save

Express

If you are already using express or equivalent, you can do the following:

app.use("/viber/webhook", bot.middleware());

Please revisit app.use() documentation. For more information see ViberBot.middleware().

Let’s get started!

Creating a basic Viber bot is simple:

  1. Create bot
  2. Import viber-bot library to your project
  3. Use the authentication token from your Viber account settings.
  4. Configure your bot as described in the documentation below
  5. Add the bot as middleware to your server with bot.middleware()
  6. Start your web server
  7. Call setWebhook(url) with your web server url

Creating an echo Bot

Firstly, let’s import and configure our bot:

'use strict';

const ViberBot = require('viber-bot').Bot;
const BotEvents = require('viber-bot').Events;

const bot = new ViberBot({
	authToken: YOUR_AUTH_TOKEN_HERE,
	name: "EchoBot",
	avatar: "https://viber.com/avatar.jpg" // It is recommended to be 720x720, and no more than 100kb.
});

// Perfect! Now here's the key part:
bot.on(BotEvents.MESSAGE_RECEIVED, (message, response) => {
	// Echo's back the message to the client. Your bot logic should sit here.
	response.send(message);
});

// Wasn't that easy? Let's create HTTPS server and set the webhook:
const https = require('https');
const port = process.env.PORT || 8080;

// Viber will push messages sent to this URL. Web server should be internet-facing.
const webhookUrl = process.env.WEBHOOK_URL;

const httpsOptions = {
	key: ...,
	cert: ...,
	ca: ...
}; // Trusted SSL certification (not self-signed).
https.createServer(httpsOptions, bot.middleware()).listen(port, () => bot.setWebhook(webhookUrl));

Using Winston logger

We provide an option to use Winston logger with our library. The only requirement is that you use Winston >= 2.0.0.

'use strict';

const ViberBot = require('viber-bot').Bot;
const winston = require('winston');
const toYAML = require('winston-console-formatter'); // makes the output more friendly

function createLogger() {
	const logger = new winston.Logger({
		level: "debug"
	}); // We recommend DEBUG for development
	logger.add(winston.transports.Console, toYAML.config());
	return logger;
}

const logger = createLogger();
const bot = new ViberBot({
	logger: logger,
	authToken: ...,
	...
});

Do you supply a basic router for text messages?

Well funny you ask. Yes we do. But a word of warning - messages sent to your router callback will also be emitted to the BotEvents.MESSAGE_RECEIVED event.

const TextMessage = require('viber-bot').Message.Text;

// A simple regular expression to answer messages in the form of 'hi' and 'hello'.
bot.onTextMessage(/^hi|hello$/i, (message, response) =>
    response.send(new TextMessage(`Hi there ${response.userProfile.name}. I am ${bot.name}`)));

Have you noticed how we created the TextMessage instance? There’s a all bunch of message types you should get familiar with.

Creating them is easy! Every message object has its own unique constructor corresponding to its API implementation. Click on each type in the list to find out more. Check out the full API documentation for more advanced uses.

API

Viber Bot

require('viber-bot').Bot

An event emitter, emitting events described here.

New ViberBot()

Param Type Description
options.logger object Winston logger
options.authToken string Viber Auth Token
options.name string Your BOT Name
options.avatar string Avatar URL. No more than 100kb.
options.registerToEvents array example: [“message”, “delivered”]

bot.on(handler)

require('viber-bot').Events

Param Type
handler EventHandlerCallback
message Message Object
response Response Object
err Error Object

Subscribe to events:

  • MESSAGE_RECEIVED (Callback: function (message, response) {})
  • MESSAGE_SENT (Callback: function (message, userProfile) {})
  • SUBSCRIBED (Callback: function (response) {})
  • UNSUBSCRIBED (Callback: function (response) {})
  • CONVERSATION_STARTED (Callback: function (userProfile, isSubscribed, context, onFinish) {})
  • ERROR (Callback: function (err) {})

Example

bot.on(BotEvents.MESSAGE_RECEIVED, (message, response) => ... );
bot.on(BotEvents.MESSAGE_SENT, (message, userProfile) => ... );
bot.on(BotEvents.CONVERSATION_STARTED, (userProfile, isSubscribed, context, onFinish) => ... );
bot.on(BotEvents.ERROR, err => ... );
bot.on(BotEvents.UNSUBSCRIBED, response => ... );
bot.on(BotEvents.SUBSCRIBED, response =>
    response.send(`Thanks for subscribing, ${response.userProfile.name}`));

bot.getBotProfile()

Returns a promise.JSON with the following JSON.

bot.getBotProfile().then(response => console.log(`Bot Named: ${response.name}`));

bot.getUserDetails(userProfile)

Param Type Description
userProfile UserProfile UserProfile object

The getUserDetails function will fetch the details of a specific Viber user based on his unique user ID. The user ID can be obtained from the callbacks sent to the account regarding user’s actions. This request can be sent twice during a 12 hours period for each user ID.

Returns a promise.JSON.

bot.onSubscribe(response => bot.getUserDetails(response.userProfile)
        .then(userDetails => console.log(userDetails)));

bot.getOnlineStatus(viberUserIds)

Param Type Description
viberUserIds array of strings Collection of Viber user ids

Returns a promise.JSON.

bot.getOnlineStatus(["a1, "a2"]).then(onlineStatus => console.log(onlineStatus));

bot.setWebhook(url)

Param Type Description
url string Trusted SSL Certificate

Returns a promise.JSON.

bot.setWebhook("https://my.bot/incoming").then(() => yourBot.doSomething()).catch(err => console.log(err));

bot.sendMessage(userProfile, messages, [optionalTrackingData])

Param Type Description
userProfile UserProfile UserProfile object
messages object or array Can be Message object or array of Message objects
[optionalTrackingData] JSON Optional. JSON Object. Returned on every message sent by the client

Note: When passing array of messages to sendMessage, messages will be sent by explicit order (the order which they were given to the sendMessage method). The library will also cancel all custom keyboards except the last one, sending only the last message keyboard.

Returns a promise.ARRAY array of message tokens.

// Single message
const TextMessage = require('viber-bot').Message.Text;
bot.sendMessage(userProfile, new TextMessage("Thanks for shopping with us"));

// Multiple messages
const UrlMessage = require('viber-bot').Message.Url;
bot.sendMessage(userProfile, [
	new TextMessage("Here's the product you've requested:"),
	new UrlMessage("https://my.ecommerce.site/product1"),
	new TextMessage("Shipping time: 1-3 business days")
]);

bot.middleware()

Returns a middleware implementation to use with http/https.

const https = require('https');
https.createServer({
	key: ...,
	cert: ...,
	ca: ...
}, bot.middleware()).listen(8080);

bot.onTextMessage(regex, handler)

Param Type
regex regular expression
handler TextMessageHandlerCallback

TextMessageHandlerCallback: function (message, response) {}
bot.onTextMessage(/^hi|hello$/i, (message, response) =>
    response.send(new TextMessage(`Hi there ${response.userProfile.name}. I am ${bot.name}`)));

bot.onError(handler)

Param Type
handler ErrorHandlerCallback

ErrorHandlerCallback: function (err) {}
bot.onError(err => logger.error(err));

bot.onConversationStarted(userProfile, isSubscribed, context, onFinish)

Param Type Description
userProfile UserProfile UserProfile object
isSubscribed boolean Indicates whether a user is already subscribed
context String Any additional parameters added to the deep link used to access the conversation passed as a string
onFinish ConversationStartedOnFinishCallback When called, a Message will be sent to the client

Conversation started event fires when a user opens a conversation with the bot using the “message” button (found on the account’s info screen) or using a deep link.

This event is not considered a subscribe event and doesn’t allow the account to send messages to the user; however, it will allow sending one “welcome message” to the user. See sending a welcome message below for more information.

ConversationStartedOnFinishCallback: function (responseMessage, optionalTrackingData) {}

The ConversationStartedOnFinishCallback accepts null and MessageObject only. Otherwise, an exception is thrown.

bot.onConversationStarted((userProfile, isSubscribed, context, onFinish) =>
	onFinish(new TextMessage(`Hi, ${userProfile.name}! Nice to meet you.`)));

bot.onConversationStarted((userProfile, isSubscribed, context, onFinish) =>
	onFinish(new TextMessage(`Thanks`), {
		saidThanks: true
	}));

The ConversationStartedOnFinishCallback isn’t compatible with certain keyboard features, and therefore sendMessage is preferable when sending messages with keyboards.

const KEYBOARD_JSON = {
...
}

const message = new TextMessage("new text",KEYBOARD_JSON,null,null,null,3);

bot.onConversationStarted((userProfile, isSubscribed, context) =>
    bot.sendMessage(userProfile,message)
);

bot.onSubscribe(handler)

Param Type
handler SubscribeResponseHandlerCallback

SubscribeResponseHandlerCallback: function (response) {}
bot.onSubscribe(response => console.log(`Subscribed: ${response.userProfile.name}`));

bot.onUnsubscribe(handler)

Param Type
handler UnsubscribeResponseHandlerCallback

UnsubscribeResponseHandlerCallback: function (userId) {}
bot.onUnsubscribe(userId => console.log(`Unsubscribed: ${userId}`));

Response object

Members:

Param Type Notes
userProfile UserProfile

UserProfile object

Members:

Param Type Notes
id string
name string
avatar string Optional Avatar URL
country string currently set in CONVERSATION_STARTED event only
language string currently set in CONVERSATION_STARTED event only

Message Object

const TextMessage = require('viber-bot').Message.Text;
const UrlMessage = require('viber-bot').Message.Url;
const ContactMessage = require('viber-bot').Message.Contact;
const PictureMessage = require('viber-bot').Message.Picture;
const VideoMessage = require('viber-bot').Message.Video;
const LocationMessage = require('viber-bot').Message.Location;
const StickerMessage = require('viber-bot').Message.Sticker;
const RichMediaMessage = require('viber-bot').Message.RichMedia;
const KeyboardMessage = require('viber-bot').Message.Keyboard;

Common Members for Message interface:

Param Type Description
timestamp string Epoch time
token string Sequential message token
trackingData JSON JSON Tracking Data from Viber Client

Common Constructor Arguments Message interface:

Param Type Description
optionalKeyboard JSON Writing Custom Keyboards
optionalTrackingData JSON Data to be saved on Viber Client device, and sent back each time message is received

TextMessage object

Member Type
text string
const message = new TextMessage(text, [optionalKeyboard], [optionalTrackingData]);
console.log(message.text);

Note: to enable features that have an api level requirement in your keyboard, it’s necessary to add the following arguments to the KeyboardMessage constructor: TextMessage(text, [optionalKeyboard], [optionalTrackingData], null, null, [minApiVersion]) [minApiVersion] should be an integer value of the desired minimum api version/level for the message.

UrlMessage object

Member Type
url string
const message = new UrlMessage(url, [optionalKeyboard], [optionalTrackingData]);
console.log(message.url);

ContactMessage object

Member Type
contactName string
contactPhoneNumber string
const message = new ContactMessage(contactName, contactPhoneNumber, [optionalAvatar], [optionalKeyboard], [optionalTrackingData]);
console.log(`${message.contactName}, ${message.contactPhoneNumber}`);

PictureMessage object

Member Type
url string
text string
thumbnail string
const message = new PictureMessage(url, [optionalText], [optionalThumbnail], [optionalKeyboard], [optionalTrackingData]);
console.log(`${message.url}, ${message.text}, ${message.thumbnail}`);

VideoMessage object

Member Type
url string
size int
thumbnail string
duration int
const message = new VideoMessage(url, size, [optionalText], [optionalThumbnail], [optionalDuration], [optionalKeyboard], [optionalTrackingData]);
console.log(`${message.url}, ${message.size}, ${message.thumbnail}, ${message.duration}`);

LocationMessage object

Member Type
latitude float
longitude float
const message = new LocationMessage(latitude, longitude, [optionalKeyboard], [optionalTrackingData]);
console.log(`${message.latitude}, ${message.longitude}`);

StickerMessage object

Member Type
stickerId int
const message = new StickerMessage(stickerId, [optionalKeyboard], [optionalTrackingData]);
console.log(message.stickerId);

FileMessage object

Member Type
url string
sizeInBytes int
filename string
const message = new FileMessage(url, sizeInBytes, filename, [optionalKeyboard], [optionalTrackingData]);
console.log(`${message.url}, ${message.sizeInBytes}, ${message.filename}`);

RichMediaMessage object

Member Type
richMedia Object
const SAMPLE_RICH_MEDIA = {
	"ButtonsGroupColumns": 6,
	"ButtonsGroupRows": 2,
	"BgColor": "#FFFFFF",
	"Buttons": [{
		"ActionBody": "https://www.website.com/go_here",
		"ActionType": "open-url",
		"BgMediaType": "picture",
		"Image": "https://www.images.com/img.jpg",
		"BgColor": "#000000",
		"TextOpacity": 60,
		"Rows": 4,
		"Columns": 6
	}, {
		"ActionBody": "https://www.website.com/go_here",
		"ActionType": "open-url",
		"BgColor": "#85bb65",
		"Text": "Buy",
		"TextOpacity": 60,
		"Rows": 1,
		"Columns": 6
	}]
};

const message = new RichMediaMessage(SAMPLE_RICH_MEDIA, [optionalKeyboard], [optionalTrackingData]);

KeyboardMessage object

Member Type
keyboard JSON
const SAMPLE_KEYBOARD = {
	"Type": "keyboard",
	"Revision": 1,
	"Buttons": [
		{
			"Columns": 3,
			"Rows": 2,
			"BgColor": "#e6f5ff",
			"BgMedia": "https://www.jqueryscript.net/images/Simplest-Responsive-jQuery-Image-Lightbox-Plugin-simple-lightbox.jpg",
			"BgMediaType": "picture",
			"BgLoop": true,
			"ActionType": "reply",
			"ActionBody": "Yes"
		}
	]
};

const message = new KeyboardMessage(SAMPLE_KEYBOARD, [optionalTrackingData]);

Note: to enable features that have an api level requirement in your keyboard, it’s necessary to add the following arguments to the KeyboardMessage constructor: KeyboardMessage(SAMPLE_KEYBOARD, [optionalTrackingData], null, null, [minApiVersion]) [minApiVersion] should be an integer value of the desired minimum api version/level for the message.

Sample project

We’ve created the Is It Up sample project to help you get started.

Community

Join the conversation on Gitter.


Viber Python Bot API

Use this library to develop a bot for Viber platform. The library is available on GitHub as well as a package on PyPI.

This package can be imported using pip by adding the following to your requirements.txt:

viberbot==1.0.11

Important notes for bot developers: Please note that since 5.02.24, Viber bots can only be created on commercial terms. Before you start developing your bot in Viber please check how to apply for a bot creation here.

License

This library is released under the terms of the Apache 2.0 license. See License for more information.

Library Prerequisites

  1. python >= 2.7.0
  2. An Active Viber account on a platform which supports bots (iOS/Android). This account be set as the account administrator during the account creation process.
  3. Active bot.
  4. Account authentication token - unique account identifier used to validate your account in all API requests. Once your account is created your authentication token will appear in the account’s “edit info” screen (for admins only). Each request posted to Viber by the account will need to contain the token.
  5. Webhook - Please use a server endpoint URL that supports HTTPS. If you deploy on your own custom server, you’ll need a trusted (ca.pem) certificate, not self-signed. Read our blog post on how to test your bot locally.

Let’s get started!

Installing

Creating a basic Viber bot is simple:

  1. Create bot
  2. Install the library with pip pip install viberbot
  3. Import viberbot.api library to your project
  4. Use the authentication token from your Viber account settings
  5. Configure your bot as described in the documentation below
  6. Start your web server
  7. Call set_webhook(url) with your web server url

A simple Echo Bot

Firstly, let’s import and configure our bot

from viberbot import Api
from viberbot.api.bot_configuration import BotConfiguration

bot_configuration = BotConfiguration(
	name='PythonSampleBot',
	avatar='https://viber.com/avatar.jpg',
	auth_token='YOUR_AUTH_TOKEN_HERE'
)
viber = Api(bot_configuration)

Create an HTTPS server

Next thing you should do is starting a https server. and yes, as we said in the prerequisites it has to be https server. Create a server however you like, for example with Flask:

from flask import Flask, request, Response

app = Flask(__name__)

@app.route('/incoming', methods=['POST'])
def incoming():
	logger.debug("received request. post data: {0}".format(request.get_data()))
	# handle the request here
	return Response(status=200)

context = ('server.crt', 'server.key')
app.run(host='0.0.0.0', port=443, debug=True, ssl_context=context)

Setting a webhook

After the server is up and running you can set a webhook. Viber will push messages sent to this URL. web server should be internet-facing.

viber.set_webhook('https://mybotwebserver.com:443/')

Logging

This library uses the standard python logger. If you want to see its logs you can configure the logger:

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

Do you supply a basic types of messages?

Well, funny you ask. Yes we do. All the Message types are located in viberbot.api.messages package. Here’s some examples:

from viberbot.api.messages import (
    TextMessage,
    ContactMessage,
    PictureMessage,
    VideoMessage
)
from viberbot.api.messages.data_types.contact import Contact

# creation of text message
text_message = TextMessage(text="sample text message!")

# creation of contact message
contact = Contact(name="Viber user", phone_number="0123456789")
contact_message = ContactMessage(contact=contact)

# creation of picture message
picture_message = PictureMessage(text="Check this", media="https://site.com/img.jpg")

# creation of video message
video_message = VideoMessage(media="https://mediaserver.com/video.mp4", size=4324)

Have you noticed how we created the TextMessage? There’s a all bunch of message types you should get familiar with.

Creating them is easy! Every message object has it’s own unique constructor corresponding to it’s API implementation, click on them to see it! Check out the full API documentation for more advanced uses.

Let’s add it all up and reply with a message!

from flask import Flask, request, Response
from viberbot import Api
from viberbot.api.bot_configuration import BotConfiguration
from viberbot.api.messages import VideoMessage
from viberbot.api.messages.text_message import TextMessage
import logging

from viberbot.api.viber_requests import ViberConversationStartedRequest
from viberbot.api.viber_requests import ViberFailedRequest
from viberbot.api.viber_requests import ViberMessageRequest
from viberbot.api.viber_requests import ViberSubscribedRequest
from viberbot.api.viber_requests import ViberUnsubscribedRequest

app = Flask(__name__)
viber = Api(BotConfiguration(
    name='PythonSampleBot',
    avatar='https://site.com/avatar.jpg',
    auth_token='445da6az1s345z78-dazcczb2542zv51a-e0vc5fva17480im9'
))


@app.route('/', methods=['POST'])
def incoming():
    logger.debug("received request. post data: {0}".format(request.get_data()))
    # every viber message is signed, you can verify the signature using this method
    if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')):
        return Response(status=403)

    # this library supplies a simple way to receive a request object
    viber_request = viber.parse_request(request.get_data())

    if isinstance(viber_request, ViberMessageRequest):
        message = viber_request.message
        # lets echo back
        viber.send_messages(viber_request.sender.id, [
            message
        ])
    elif isinstance(viber_request, ViberSubscribedRequest):
        viber.send_messages(viber_request.get_user.id, [
            TextMessage(text="thanks for subscribing!")
        ])
    elif isinstance(viber_request, ViberFailedRequest):
        logger.warn("client failed receiving message. failure: {0}".format(viber_request))

    return Response(status=200)

if __name__ == "__main__":
    context = ('server.crt', 'server.key')
    app.run(host='0.0.0.0', port=443, debug=True, ssl_context=context)

As you can see there’s a bunch of Request types here’s a list of them.

Viber API

Api class

from viberbot import Api

New Api()

Param Type Description
bot_configuration object BotConfiguration

Api.set_webhook(url)

Param Type Description
url string Your web server url
webhook_events list optional list of subscribed events

Returns List of registered event_types.

event_types = viber.set_webhook('https://example.com/incoming')

Api.unset_webhook()

Returns None.

viber.unset_webhook()

Api.get_account_info()

Returns an object with the following JSON.

account_info = viber.get_account_info()

Api.verify_signature(request_data, signature)

Param Type Description
request_data string the post data from request
signature string sent as header X-Viber-Content-Signature

Returns a boolean suggesting if the signature is valid.

if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')):
	return Response(status=403)

Api.parse_request(request_data)

Param Type Description
request_data string the post data from request

Returns a ViberRequest object.

There’s a list of ViberRequest objects

viber_request = viber.parse_request(request.get_data())

Api.send_messages(to, messages)

Param Type Description
to string Viber user id
messages list list of Message objects

Returns list of message tokens of the messages sent.

tokens = viber.send_messages(to=viber_request.get_sender().get_id(),
			     messages=[TextMessage(text="sample message")])

Api.get_online(viber_user_ids)

Param Type Description
viber_user_ids array of strings Array of Viber user ids

Returns a dictionary of users.

users = Api.get_online(["user1id", "user2id"])

Api.get_user_details(viber_user_id)

Param Type Description
viber_user_ids string Viber user id

The get_user_details function will fetch the details of a specific Viber user based on his unique user ID. The user ID can be obtained from the callbacks sent to the account regarding user’s actions. This request can be sent twice during a 12 hours period for each user ID.

user_data = Api.get_user_details("userId")

Request object

Param Type Notes
event_type string according to EventTypes enum
timestamp long Epoch of request time
  • ViberRequest
    • .event_type ⇒ string
    • .timestamp ⇒ long

ViberConversationStartedRequest object

Inherits from ViberRequest

Conversation started event fires when a user opens a conversation with the bot using the “message” button (found on the bot’s info screen) or using a deep link.

This event is not considered a subscribe event and doesn’t allow the account to send messages to the user; however, it will allow sending one “welcome message” to the user. See sending a welcome message below for more information.

Param Type Notes
event_type string always equals to the value of EventType.CONVERSATION_STARTED
message_token string Unique ID of the message
type string The specific type of conversation_started event.
context string Any additional parameters added to the deep link used to access the conversation passed as a string
user UserProfile the user started the conversation UserProfile
subscribed boolean Indicates whether a user is already subscribed
  • ViberConversationStartedRequest
    • message_token ⇒ string
    • type ⇒ string
    • context ⇒ string
    • user ⇒ UserProfile

ViberDeliveredRequest object

Inherits from ViberRequest

Param Type Notes
event_type string always equals to the value of EventType.DELIVERED
message_token string Unique ID of the message
user_id string Unique Viber user id
  • ViberDeliveredRequest
    • message_token ⇒ string
    • user_id ⇒ string

ViberFailedRequest object

Inherits from ViberRequest

Param Type Notes
event_type string always equals to the value of EventType.FAILED
message_token string Unique ID of the message
user_id string Unique Viber user id
desc string Failure description
  • ViberFailedRequest
    • message_token ⇒ string
    • user_id ⇒ string
    • desc ⇒ string

ViberMessageRequest object

Inherits from ViberRequest

Param Type Notes
event_type string always equals to the value of EventType.MESSAGE
message_token string Unique ID of the message
message Message Message object
sender UserProfile the user started the conversation UserProfile
  • ViberMessageRequest
    • message_token ⇒ string
    • message ⇒ Message
    • sender ⇒ UserProfile

ViberSeenRequest object

Inherits from ViberRequest

Param Type Notes
event_type string always equals to the value of EventType.SEEN
message_token string Unique ID of the message
user_id string Unique Viber user id
  • ViberSeenRequest
    • message_token ⇒ string
    • user_id ⇒ string

ViberSubscribedRequest object

Inherits from ViberRequest

Param Type Notes
event_type string always equals to the value of EventType.SUBSCRIBED
user UserProfile the user started the conversation UserProfile
  • ViberSubscribedRequest
    • user ⇒ UserProfile

ViberUnsubscribedRequest object

Inherits from ViberRequest

Param Type Notes
event_type string always equals to the value of EventType.UNSUBSCRIBED
user_id string Unique Viber user id
  • ViberUnsubscribedRequest
    • get_user_id() ⇒ string

UserProfile object

Param Type Notes
id string
name string
avatar string Avatar URL
country string currently set in CONVERSATION_STARTED event only
language string currently set in CONVERSATION_STARTED event only

Message Object

Common Members for Message interface:

Param Type Description
timestamp long Epoch time
keyboard JSON keyboard JSON
trackingData JSON JSON Tracking Data from Viber Client

Common Constructor Arguments Message interface:

Param Type Description
optionalKeyboard JSON Writing Custom Keyboards
optionalTrackingData JSON Data to be saved on Viber Client device, and sent back each time message is received

TextMessage object

Member Type
text string
message = TextMessage(text="my text message")

URLMessage object

Member Type Description
media string URL string
message = URLMessage(media="https://my.siteurl.com");

ContactMessage object

Member Type
contact Contact
from viberbot.api.messages.data_types.contact import Contact

contact = Contact(name="Viber user", phone_number="+0015648979", avatar="https://link.to.avatar")
contact_message = ContactMessage(contact=contact)

PictureMessage object

Member Type Description
media string url of the message (jpeg only)
text string  
thumbnail string  
message = PictureMessage(media="https://www.thehindubusinessline.com/multimedia/dynamic/01458/viber_logo_JPG_1458024f.jpg", text="Viber logo")

VideoMessage object

Member Type Description
media string url of the video
size int  
thumbnail string  
duration int  
message = VideoMessage(media="https://site.com/video.mp4", size=21499)

LocationMessage object

Member Type
location Location
from viberbot.api.messages.data_types.location import Location

location = Location(lat=0.0, lon=0.0)
location_message = LocationMessage(location=location)

StickerMessage object

Member Type
sticker_id int
message = StickerMessage(sticker_id=40100);

FileMessage object

Member Type
media string
size long
file_name string
message = FileMessage(media=url, size=sizeInBytes, file_name=file_name)

RichMediaMessage object

Member Type
rich_media string (JSON)
SAMPLE_RICH_MEDIA = {
  "BgColor": "#69C48A",
  "Buttons": [
    {
      "Columns": 6,
      "Rows": 1,
      "BgColor": "#454545",
      "BgMediaType": "gif",
      "BgMedia": "https://www.url.by/test.gif",
      "BgLoop": "true",
      "ActionType": "open-url",
      "Silent": "true",
      "ActionBody": "www.tut.by",
      "Image": "www.tut.by/img.jpg",
      "TextVAlign": "middle",
      "TextHAlign": "left",
      "Text": "<b>example</b> button",
      "TextOpacity": 10,
      "TextSize": "regular"
    }
  ]
}

SAMPLE_ALT_TEXT = "upgrade now!"

message = RichMediaMessage(rich_media=SAMPLE_RICH_MEDIA, alt_text=SAMPLE_ALT_TEXT);

KeyboardMessage object

Member Type
keyboard JSON
tracking_data JSON
SAMPLE_KEYBOARD = {
"Type": "keyboard",
"Buttons": [
	{
	"Columns": 3,
	"Rows": 2,
	"BgColor": "#e6f5ff",
	"BgMedia": "https://link.to.button.image",
	"BgMediaType": "picture",
	"BgLoop": True,
	"ActionType": "reply",
	"ActionBody": "This will be sent to your bot in a callback",
	"ReplyType": "message",
	"Text": "Push me!"
	}
    ]
}

message = KeyboardMessage(tracking_data='tracking_data', keyboard=SAMPLE_KEYBOARD)

Sending a welcome message

The Viber API allows sending messages to users only after they subscribe to the account. However, Viber will allow the account to send one “welcome message” to a user as the user opens the conversation, before the user subscribes.

The welcome message will be sent as a response to a conversation_started callback, which will be received from Viber once the user opens the conversation with the account. To learn more about this event and when is it triggered see Conversation started in the callbacks section.

Welcome message flow

Sending a welcome message will be done according to the following flow:

  1. User opens 1-on-1 conversation with account.
  2. Viber server send conversation_started even to PA’s webhook.
  3. The account receives the conversation_started and responds with an HTTP response which includes the welcome message as the response body.

The welcome message will be a JSON constructed according to the send_message requests structure, but without the receiver parameter. An example welcome message would look like this:

@app.route('/', methods=['POST'])
def incoming():
	viber_request = viber.parse_request(request.get_data())

	if isinstance(viber_request, ViberConversationStartedRequest) :
		viber.send_messages(viber_request.get_user().get_id(), [
			TextMessage(text="Welcome!")
		])

	return Response(status=200)

Community

Join the conversation on Gitter.


Viber REST API

Get Started

To implement the API, you will need the following:

  1. An Active Viber account on a platform that supports bots (iOS/Android). This account will be set as the account administrator after the account creation process.
  2. Active bot — since 5.02.24, Viber bots can only be created on commercial terms. Find out how to apply for a chatbot in Rakuten Viber here.
  3. Account authentication token - unique account identifier used to validate your account in all API requests. Each request posted to Rakuten Viber by the account will need to contain the token. When your bot is created, you will be added as an admin and the token will appear in your Viber account settings (More > Settings > Bots > Edit Info > Your app key)
  4. Set-up account webhook — this needs to be done once during the account setup process to define your webhook and the type of responses you would like to receive.

Supported platforms

Bots are currently supported on iOS and Android devices running Viber version 6.5 and above and on desktop from version 6.5.3.

Important notes for bot developers:

  1. Please note that since 5.02.24, Viber bots can only be created on commercial terms. You can apply to create chatbots on Rakuten Viber by reaching out directly to us or through our verified official partners. Please find more information here. Once you’ve created your bot, you are welcome to share it with your Rakuten Viber contacts or promote it outside Viber on your website or social media channels using a deeplink. You can also promote your chatbot using other Rakuten Viber solutions for business: for example, Viber Ads, Stickers, or Lenses.
  2. We recommend that you record the subscriber ID of each subscriber, as there’s no API for fetching all subscriber IDs for your bot. You can find the subscriber ID in the sender.id property of the Message callback, or the user.id property of the Subscribed callback. You can see whether a user is subscribed in the subscribed parameter of the conversation_started callback. Note that users’ first message to the bot will make them subscribed, but will not result in a Subscribed callback.
  3. If you wish to message users based on their phone number and using an API, we offer a service called Business Messages that supports working with an existing customer database. You can apply to use this service via one of our official partners. You can see which partners cover your geographical area in their description. Our partners will be able to provide you with further details about the service.

Send and receive message flow

The following diagram describes the flow of sending and receiving messages by the account. All API requests and callbacks mentioned in the diagram will be explained later in this document.

Authentication token

The authentication token (also known as application key) is a unique and secret account identifier. It is used to authenticate request in the Viber API and to prevent unauthorized persons from sending requests on behalf of a bot. Each API request must include an HTTP Header called X-Viber-Auth-Token containing the account’s authentication token.

HTTP header

X-Viber-Auth-Token: 445da6az1s345z78-dazcczb2542zv51a-e0vc5fva17480im9

The authentication token is generated upon bot creation and can be viewed by the account’s admins in the “edit info” screen of their bot or on the Viber Admin Panel.

Note: Failing to send the authentication token in the header will result in an error with the missing_auth_token message.

Webhooks

Once you have your token you will be able to set your account’s webhook. This webhook will be used for receiving callbacks and user messages from Viber.

Setting the webhook will be done by calling the set_webhook API with a valid & certified URL. This action defines the account’s webhook and the type of events the account wants to be notified about.

For security reasons only URLs with valid and official SSL certificate from a trusted CA will be allowed. The certificate CA should be on the Sun Java trusted root certificates list.

Once a set_webhook request is sent Viber will send a callback to the webhook to check its availability and return a response to the user. The check succeeds if the Viber server receives HTTP status 200 in response to the callback, but fails if it recieves any other status. If your set_webhook response doesn’t have "status":0, please verify that all requests to your webhook URL receive HTTP status 200 in response.

Note that once you set your webhook the 1-on-1 conversation with your account will become available. To disable 1-on-1 conversation with your account you’ll need to remove your webhook – see removing your webhook below.

Viber’s API allows you to receive user names and photos. This has been updated to comply with privacy laws and allow developers who don’t make use of user names and photos as part of their service to opt out. If you don’t use user names photos, please opt-out to default values.

To set the request, pass send_name and send_photo flags with the set_webhook request.

Note: This feature will work if the user has allowed “Content Personalisation” (More → Privacy → personal data). If the user has disallowed content personalization, you will receive placeholder values.

Setting a Webhook

Resource URL

https://chatapi.viber.com/pa/set_webhook

Post data

{
   "url":"https://my.host.com",
   "event_types":[
      "delivered",
      "seen",
      "failed",
      "subscribed",
      "unsubscribed",
      "conversation_started"
   ],
   "send_name":true,
   "send_photo":true
}

Post parameters

Name Description Validation
url required. Account webhook URL to receive callbacks & messages from users Webhook URL must use SSL Note: Viber doesn’t support self signed certificates
event_types optional. Indicates the types of Viber events that the account owner would like to be notified about. Don’t include this parameter in your request to get all events Possible values: delivered, seen, failed, subscribed, unsubscribed , conversation_started and message
send_name optional. Indicates whether or not the bot should receive the user name. Default true Possible values: true, false
send_photo optional. Indicates whether or not the bot should receive the user photo. Default true Possible values: true, false

Set webhook Response

{
   "status":0,
   "status_message":"ok",
   "event_types":[
      "subscribed",
      "unsubscribed",
      "conversation_started",
      "delivered",
      "failed",
      "message",
      "seen"
   ]
}

Response parameters

Name Description Possible values
status Action result 0 for success. In case of failure – appropriate failure status number. See error codes table for additional information
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken, badData, missingData and failure. See error codes table for additional information
event_types List of event types you will receive a callback for. Should return the same values sent in the request delivered, seen, failed, subscribed, unsubscribed , conversation_started and message

Event types filtering

The event_types parameter allows accounts to choose which events they would get a callback for.
The following events are mandatory and can’t be filtered out: message, subscribed and unsubscribed.
The following events can be filtered out during the set_webhook request: delivered, seen, failed and conversation_started.
Sending a set_webhook request with no event_types parameter means getting all events.
Sending a set_webhook request with empty event_types list ("event_types": []) means getting only mandatory events. See callbacks section for full callbacks events information.

Set webhook callback

For each set_webhook request Viber will send a callback to the webhook URL to confirm it is available. The expected HTTP response to the callback is 200 OK – any other response will mean the webhook is not available. If the webhook is not available the set_webhook response sent to the user will be status 1: invalidUrl.

Callback data
{
   "event":"webhook",
   "timestamp":1457764197627,
   "message_token":241256543215
}

Callback parameters

Name Description Possible values
event Callback type – which event triggered the callback webhook
timestamp Time of the event that triggered the callback Epoch time
message_token Unique ID of the message  

Removing your webhook

Once you set a webhook to your bot your 1-on-1 conversation button will appear and users will be able to access it.
At the moment there is no option to disable the 1-on-1 conversation from the bot settings, so to disable this option you’ll need to remove the webhook you set for the account. Removing the webhook is done by Posting a set_webhook request with an empty webhook string.

Resource URL

https://chatapi.viber.com/pa/set_webhook

Post data

{
   "url":""
}

Post parameters

Name Description
url required. Account webhook URL to receive callbacks & messages from users. In this case, use an empty string to remove any previously set webhook

Send Message

The send_message API allows accounts to send messages to Viber users who subscribe to the account. Sending a message to a user will be possible only after the user has subscribed to the bot. (see subscribed callback for additional information). You can share your bot with the users via a deeplink.

The API supports a variety of message types: text, picture, video, file, location, sticker, contact, carousel content and URL. Specific post data examples and required parameters for each message type are given below.

Validation

Maximum total JSON size of the request is 30kb.

Resource URL

https://chatapi.viber.com/pa/send_message

General send message parameters

The following parameters are available for all message types:

Name Description Validation
receiver Unique Viber user id required, subscribed valid user id
type Message type required. Available message types: text, picture, video, file, location, contact, sticker, carousel content and url
sender.name The sender’s name to display required. Max 28 characters
sender.avatar The sender’s avatar URL optional. Avatar size should be no more than 100 kb. Recommended 720x720
tracking_data Allow the account to track messages and user’s replies. Sent tracking_data value will be passed back with user’s reply optional. max 4096 characters
min_api_version Minimal API version required by clients for this message (default 1) optional. client version support the API version. Certain features may not work as expected if set to a number that’s below their requirements.

Response

Response parameters

Name Description Possible values
status Action result 0 for success. In case of failure - appropriate failure status number. See error codes table for additional information
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken, badData, missingData and failure. See error codes table for additional information
message_token Unique ID of the message  
chat_hostname Internal use  
billing_status An indication of how this message is categorized for billing purposes, allowing you to know if it was charged or not An integer between 0 and 5. See below an explanation for all possible values.

Below you can find the possible values for the billing_status parameter:

Value Description
0 Default for all cases other than the ones listed below: chat extension, reply to open conversation, etc.
1 1:1 message/keyboard sent in a session
2 1:1 message/keyboard sent in a session
3 Free out of session 1:1 message/keyboard
4 Free out of session 1:1 message/keyboard
5 Charged out of session 1:1 message/keyboard

Response example:

{
   "status":0,
   "status_message":"ok",
   "message_token":5741311803571721087,
   "chat_hostname":"SN-CHAT-05_",
   "billing_status":1
}

Message types

Below is a list of all supported message types with post data examples.

Text message

Post data
{
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"text",
   "text":"Hello world!"
}

Post parameters

Name Description Validation
type Message type required. text. Supports text formatting
text The text of the message required. Max length 7,000 characters

Picture message

Post data
{  
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{  
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"picture",
   "text":"Photo description",
   "media":"https://www.images.com/img.jpg",
   "thumbnail":"https://www.images.com/thumb.jpg"
}

Post parameters

Name Description Validation
type Message type required. picture
text Description of the photo. Can be an empty string if irrelevant required. Max 768 characters
media URL of the image (JPEG, PNG, non-animated GIF) required. The URL must have a resource with a .jpeg, .png or .gif file extension as the last path segment. Example: https://www.example.com/path/image.jpeg. Max image size: 1MB on iOS, 3MB on Android. Note GIFs are only static. To send animated GIFs please check URL message
thumbnail URL of a reduced size image (JPEG, PNG, GIF) optional. Recommended: 400x400. Max size: 100kb.

Video message

Post data
{  
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{  
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"video",
   "media":"https://www.images.com/video.mp4",
   "thumbnail":"https://www.images.com/thumb.jpg",
   "size":10000,
   "duration":10
}

Post parameters

Name Description Validation
type Message type required. video
media URL of the video (MP4, H264) required. Max size 26 MB. Only MP4 and H264 are supported. The URL must have a resource with a .mp4 file extension as the last path segment. Example: https://www.example.com/path/video.mp4
size Size of the video in bytes required
duration Video duration in seconds; will be displayed to the receiver optional. Max 180 seconds
thumbnail URL of a reduced size image (JPEG) optional. Max size 100 kb. Recommended: 400x400. Only JPEG format is supported

File message

Post data
{  
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{  
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"file",
   "media":"https://www.images.com/file.doc",
   "size":10000,
   "file_name":"name_of_file.doc"
}

Post parameters

Name Description Validation
type Message type required. file
media URL of the file required. Max size 50 MB. URL should include the file extension. See forbidden file formats for unsupported file types
size Size of the file in bytes required
file_name Name of the file required. File name should include extension. Max 256 characters (including file extension). Sending a file without extension or with the wrong extension might cause the client to be unable to open the file

Contact message

Post data
{
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"contact",
   "contact":{
      "name":"Itamar",
      "phone_number":"+972511123123"
   }
}

Post parameters

Name Description Validation
type Message type required. contact
contact.name Name of the contact required. Max 28 characters
contact.phone_number Phone number of the contact required. Max 18 characters

Location message

Post data
{
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"location",
   "location":{
      "lat":"37.7898",
      "lon":"-122.3942"
   }
}

Post parameters

Name Description Validation
type Message type required. location
location Location coordinates required. latitude (±90°) & longitude (±180°) within valid ranges

URL message

Post data
{
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"url",
   "media":"https://www.website.com/go_here"
}

Post parameters

Name Description Validation
type Message type required. url
media URL, GIF required. Max 2,000 characters

Sticker message

Post data
{
   "receiver":"01234567890A=",
   "min_api_version":1,
   "sender":{
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "tracking_data":"tracking data",
   "type":"sticker",
   "sticker_id":46105
}

Post parameters

Name Description Validation
type Message type required. sticker
sticker_id Unique Viber sticker ID. For examples visit the sticker IDs page  

The Rich Media message type allows sending messages with pre-defined layout, including height (rows number), width (columns number), text, images and buttons.

Below you will find an exmaple of a Carousel Content Message, that allows a user to scroll through a list of items, each composed of an image, description and call to action button.

Each item on the list shown to the user is a button in the Rich Media message’s “Buttons” array. Sending one button is also permitted.

The parameters for Rich Media message and its buttons are also used for Keyboards. You can find additional information on them in the following article.

Notes:

  1. Carousel Content Message is supported on devices running Viber version 6.7 and above.
  2. Each button is limited to a maximum of 7 rows.
  3. Forwarding is not supported for Rich Media messages.
  4. ActionTypes location-picker and share-phone are not supported for Rich Media messages.
Post data
{
   "receiver":"nsId6t9MWy3mq09RAeXiug==",
   "type":"rich_media",
   "min_api_version":7,
   "rich_media":{
      "Type":"rich_media",
      "ButtonsGroupColumns":6,
      "ButtonsGroupRows":7,
      "BgColor":"#FFFFFF",
      "Buttons":[
         {
            "Columns":6,
            "Rows":3,
            "ActionType":"open-url",
            "ActionBody":"https://www.google.com",
            "Image":"https://html-test:8080/myweb/guy/assets/imageRMsmall2.png"
         },
         {
            "Columns":6,
            "Rows":2,
            "Text":"<font color=#323232><b>Headphones with Microphone, On-ear Wired earphones</b></font><font color=#777777><br>Sound Intone </font><font color=#6fc133>$17.99</font>",
            "ActionType":"open-url",
            "ActionBody":"https://www.google.com",
            "TextSize":"medium",
            "TextVAlign":"middle",
            "TextHAlign":"left"
         },
         {
            "Columns":6,
            "Rows":1,
            "ActionType":"reply",
            "ActionBody":"https://www.google.com",
            "Text":"<font color=#ffffff>Buy</font>",
            "TextSize":"large",
            "TextVAlign":"middle",
            "TextHAlign":"middle",
            "Image":"https://s14.postimg.org/4mmt4rw1t/Button.png"
         },
         {
            "Columns":6,
            "Rows":1,
            "ActionType":"reply",
            "ActionBody":"https://www.google.com",
            "Text":"<font color=#8367db>MORE DETAILS</font>",
            "TextSize":"small",
            "TextVAlign":"middle",
            "TextHAlign":"middle"
         },
         {
            "Columns":6,
            "Rows":3,
            "ActionType":"open-url",
            "ActionBody":"https://www.google.com",
            "Image":"https://s16.postimg.org/wi8jx20wl/image_RMsmall2.png"
         },
         {
            "Columns":6,
            "Rows":2,
            "Text":"<font color=#323232><b>Hanes Men's Humor Graphic T-Shirt</b></font><font color=#777777><br>Hanes</font><font color=#6fc133>$10.99</font>",
            "ActionType":"open-url",
            "ActionBody":"https://www.google.com",
            "TextSize":"medium",
            "TextVAlign":"middle",
            "TextHAlign":"left"
         },
         {
            "Columns":6,
            "Rows":1,
            "ActionType":"reply",
            "ActionBody":"https://www.google.com",
            "Text":"<font color=#ffffff>Buy</font>",
            "TextSize":"large",
            "TextVAlign":"middle",
            "TextHAlign":"middle",
            "Image":"https://s14.postimg.org/4mmt4rw1t/Button.png"
         },
         {
            "Columns":6,
            "Rows":1,
            "ActionType":"reply",
            "ActionBody":"https://www.google.com",
            "Text":"<font color=#8367db>MORE DETAILS</font>",
            "TextSize":"small",
            "TextVAlign":"middle",
            "TextHAlign":"middle"
         }
      ]
   }
}

Post parameters

Name Description Possible values
alt_text Backward compatibility text  
rich_media.ButtonsGroupColumns Number of columns per carousel content block. Default 6 columns 1 - 6
rich_media.ButtonsGroupRows Number of rows per carousel content block. Default 7 rows 1 - 7
rich_media.Buttons Array of buttons Max of 6 * ButtonsGroupColumns * ButtonsGroupRows

Button element

Name Description Possible values
Columns Button column span. Default ButtonsGroupColumns 1..ButtonsGroupColumns
Rows Button row span. Default ButtonsGroupRows 1..ButtonsGroupRows

Keyboards

The Viber API allows sending a custom keyboard using the send_message API, to supply the user with a set of predefined replies or actions. The keyboard can be attached to any message type or sent on it’s on. Once received, the keyboard will appear to the user instead of the device’s native keyboard. The keyboards are fully customizable and can be created and designed specifically for the account’s needs. The client will always display the last keyboard that was sent to it.

Read the following article to learn more about keyboards.

Validation

Maximum total JSON size of the request is 30kb.

Resource URL

https://chatapi.viber.com/pa/send_message

Post data

Keyboards can be attached to any message type and be sent and displayed together. To attach a keyboard to a message simply add the keyboard’s parameters to the message JSON.
The example below shows a keyboard sent with a text message (note that the keyboard doesn’t contain all optional values).

{
   "receiver":"01234567890A=",
   "min_api_version":7,
   "type":"text",
   "text":"Hello world",
   "keyboard":{
      "Type":"keyboard",
      "DefaultHeight":false,
      "Buttons":[
         {
            "ActionType":"reply",
            "ActionBody":"reply to me",
            "Text":"Key text",
            "TextSize":"regular"
         }
      ]
   }
}

Broadcast Message

The broadcast_message API allows accounts to send messages to multiple Viber users who subscribe to the account. Sending a message to a user will be possible only after the user has subscribed to the bot by sending a message to the bot.

The API supports a variety of message types: text, picture, video, file, location, sticker, contact, carousel content and URL.

Validation

Maximum total JSON size of the request is 30kb. The maximum list length is 300 receivers. The Broadcast API is used to send messages to multiple recipients with a rate limit of 500 requests in a 10 seconds window.

Resource URL

https://chatapi.viber.com/pa/broadcast_message

Post parameters

This API method uses the same parameters as the send REST API method with a few variations described below.

broadcast_list

This mandatory parameter defines the recipients for the message. Every user must be subscribed and have a valid user id. The maximum list length is 300 receivers. For example (this should be a part of the full JSON body):

{  
   "broadcast_list":[  
      "ABB102akPCRKFaqxWnafEIA==",
      "ABB102akPCRKFaqxWna111==",
      "ABB102akPCRKFaqxWnaf222=="
   ]
}

Place holders

Broadcast message can contain place holders that will be replaced with receiver information (each receiver will get it’s own information). The place holders can appear anywhere in the message, even in tracking data. The list of the place holders:

  • replace_me_with_receiver_id - will be replaced by the receiver ID
  • replace_me_with_url_encoded_receiver_id - will be replaced by the URL encoded receiver ID
  • replace_me_with_user_name - will be replaced by the receiver user name

Post example

The following example demonstrates send carousel content with place holders (replace_me_with_receiver_id, replace_me_with_url_encoded_receiver_id, replace_me_with_user_name) to 4 receivers:

{
   "sender":{
      "name":"John McClane",
      "avatar":"https://avatar.example.com"
   },
   "min_api_version":2,
   "type":"rich_media",
   "broadcast_list":[
      "pttm25kSGUo1919sBORWyA==",
      "2yBSIsbzs7sSrh4oLm2hdQ==",
      "EGAZ3SZRi6zW1D0uNYhQHg==",
      "kBQYX9LrGyF5mm8JTxdmpw=="
   ],
   "rich_media":{
      "Type":"rich_media",
      "BgColor":"#FFFFFF",
      "Buttons":[
         {
            "ActionBody":"https://www.google.com",
            "ActionType":"open-url",
            "Text":"Should get back my ID instead of replace_me_with_receiver_id"
         },
         {
            "ActionBody":"https://www.google.com",
            "ActionType":"open-url",
            "Text":"Should get back my URL encoded ID instead of replace_me_with_url_encoded_receiver_id"
         },
         {
            "ActionBody":"https://www.google.com",
            "ActionType":"open-url",
            "Text":"Should get back my name instead of replace_me_with_user_name"
         }
      ]
   }
}

Response

Response parameters

Name Description Possible values
message_token Unique ID of the message  
status Action result 0 for success. In case of failure – appropriate failure status number. See error codes table for additional information
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken, badData, missingData and failure. See error codes table for additional information
failed_list Contains all the receivers to which the message could not be sent properly See error codes table for additional information

Response example

{
   "message_token":40808912438712,
   "status":0,
   "status_message":"ok",
   "failed_list":[
      {
         "receiver":"pttm25kSGUo1919sBORWyA==",
         "status":6,
         "status_message":"Not subscribed"
      },
      {
         "receiver":"EGAZ3SZRi6zW1D0uNYhQHg==",
         "status":5,
         "status_message":"Not found"
      }
   ]
}

Get Account Info

The get_account_info request will fetch the account’s details as registered in Viber. The account admin will be able to edit most of these details from his Viber client.

Resource URL

https://chatapi.viber.com/pa/get_account_info

Post data

{
}

Response

{
   "status":0,
   "status_message":"ok",
   "id":"pa:75346594275468546724",
   "name":"account name",
   "uri":"accountUri",
   "icon":"https://example.com",
   "background":"https://example.com",
   "category":"category",
   "subcategory":"sub category",
   "location":{
      "lon":0.1,
      "lat":0.2
   },
   "country":"UK",
   "webhook":"https://my.site.com",
   "event_types":[
      "delivered",
      "seen"
   ],
   "subscribers_count":35,
   "members":[
      {
         "id":"01234567890A=",
         "name":"my name",
         "avatar":"https://example.com",
         "role":"admin"
      }
   ]
}

Response parameters

Name Description Possible values
status Action result 0 for success. In case of failure – appropriate failure status number. See error codes table for additional information
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken, badData, missingData and failure. See error codes table for additional information
id Unique numeric id of the account  
name Account name Max 75 characters
uri Unique URI of the Account  
icon Account icon URL JPEG, 720x720, size no more than 512 kb
background Conversation background URL JPEG, max 1920x1920, size no more than 512 kb
category Account category  
subcategory Account sub-category  
location Account location (coordinates). Will be used for finding accounts near me lat & lon coordinates
country Account country 2 letters country code - ISO ALPHA-2 Code
webhook Account registered webhook webhook URL
event_types Account registered events – as set by set_webhook request delivered, seen, failed and conversation_started
subscribers_count Number of subscribers  
members Members of the bot’s public chat id, name, avatar, role for each Public Chat member (admin/participant). Deprecated.

Get User Details

The get_user_details request will fetch the details of a specific Viber user based on his unique user ID. The user ID can be obtained from the callbacks sent to the account regarding user’s actions. This request can be sent twice during a 12 hours period for each user ID.

Resource URL

https://chatapi.viber.com/pa/get_user_details

Post data

{
   "id":"01234567890A="
}

Post parameters

Name Description Validation
id Unique Viber user id required. subscribed valid user id

Response

{
   "status":0,
   "status_message":"ok",
   "message_token":4912661846655238145,
   "user":{
      "id":"01234567890A=",
      "name":"John McClane",
      "avatar":"https://avatar.example.com",
      "country":"UK",
      "language":"en",
      "primary_device_os":"android 7.1",
      "api_version":1,
      "viber_version":"6.5.0",
      "mcc":1,
      "mnc":1,
      "device_type":"iPhone9,4"
   }
}

Response parameters

Name Description Possible values
status Action result 0 for success. In case of failure – appropriate failure status number. See error codes table for additional information
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken, badData, receiverNoSuitableDevice, missingData and failure. See error codes table for additional information
message_token Unique id of the message  
user.id Unique Viber user id  
user.name User’s Viber name  
user.avatar URL of the user’s avatar  
user.country User’s country code 2 letters country code - ISO ALPHA-2 Code
user.language The language set in the user’s Viber settings. ISO 639-1
user.primary_device_os The operating system type and version of the user’s primary device.  
user.api_version Max API version, matching the most updated user’s device Currently only 1. Additional versions will be added in the future
user.viber_version The Viber version installed on the user’s primary device  
user.mcc Mobile country code  
user.mnc Mobile network code  
user.device_type The user’s device type  

Get Online

The get_online request will fetch the online status of a given subscribed account members. The API supports up to 100 user id per request and those users must be subscribed to the account.

Resource URL

https://chatapi.viber.com/pa/get_online

Post data

{  
   "ids":[  
      "01234567890=",
      "01234567891=",
      "01234567893="
   ]
}

Post parameters

Name Description Validation
ids Unique Viber user id required. 100 ids per request

Response

{
   "status":0,
   "status_message":"ok",
   "users":[
      {
         "id":"01234567890=",
         "online_status":0,
         "online_status_message":"online"
      },
      {
         "id":"01234567891=",
         "online_status":1,
         "online_status_message":"offline",
         "last_online":1457764197627
      },
      {
         "id":"01234567893=",
         "online_status":3,
         "online_status_message":"tryLater"
      }
   ]
}

Response parameters

Name Description Possible values  
status Action result 0 for success. In case of failure – appropriate failure status number. See error codes table for additional information  
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken, badData, missingData and failure. See error codes table for additional information  
user[x].id Unique Viber user id    
user[x].online_status Online status code 0 for online, 1 for offline, 2 for undisclosed - user set Viber to hide status, 3 for try later - internal error, 4 for unavailable - not a Viber user / unsubscribed / unregistered  
user[x]. online_status_message Online status message    

Callbacks

Each callback will contain a signature on the JSON passed to the callback. The signature is HMAC with SHA256 that will use the authentication token as the key and the JSON as the value. The result will be passed as HTTP Header X-Viber-Content-Signature so the receiver can determine the origin of the message.

Re-try logic

In case the webhook is offline Viber will re-try to deliver the callback until HTTP status code 200 is received. There will be 10 retry attempts with exponential intervals:

  • 1: 10 seconds
  • 2: 60 seconds
  • 3: 300 seconds
  • 4: 600 seconds
  • 5-10: 900 seconds

Input

Key (your bot’s authentication token):

4453b6ac12345678-e02c5f12174805f9-daec9cbb5448c51f

Value:

{  
   "event":"delivered",
   "timestamp":1457764197627,
   "message_token":491266184665523145,
   "user_id":"01234567890A="
}

Output

HTTP header

X-Viber-Content-Signature: b8046cb85baaa7909d211779da609db0bd4e3c3cf63620a66a80b3e0a4228357  

Subscribed

Before an account can send messages to a user, the user will need to subscribe to the account. Subscribing can take place if the user sends a message to the bot - when a user sends its first message to a bot the user will be automatically subscribed to the bot. Sending the first message will not trigger a subscribe callback, only a message callback (see receive message from user section).

You will receive a subscribed event when unsubscribed users do the following:

  1. Open conversation with the bot.
  2. Tap on the 3-dots button in the top right and then on “Chat Info”.
  3. Tap on “Receive messages”.

Note: A subscribe event will delete any context or tracking_data information related to the conversation. This means that if a user had a conversation with a service and then chose to unsubscribe and subscribe again, a new conversation will be started without any information related to the old conversation.

Callback data

{
   "event":"subscribed",
   "timestamp":1457764197627,
   "user":{
      "id":"01234567890A=",
      "name":"John McClane",
      "avatar":"https://avatar.example.com",
      "country":"UK",
      "language":"en",
      "api_version":1
   },
   "message_token":4912661846655238145
}

Callback parameters

Name Description Possible values
event Callback type - which event triggered the callback subscribed
timestamp Time of the event that triggered the callback Epoch time
user.id Unique Viber user id  
user.name User’s Viber name  
user.avatar URL of user’s avatar  
user.country User’s 2 letter country code ISO ALPHA-2 Code
user.language User’s phone language. Will be returned according to the device language ISO 639-1
user.api_version The maximal Viber version that is supported by all of the user’s devices  
message_token Unique ID of the message  
chat_hostname Internal use  

Unsubscribed

The user will have the option to unsubscribe from the PA. This will trigger an unsubscribed callback.

Callback data

{
   "event":"unsubscribed",
   "timestamp":1457764197627,
   "user_id":"01234567890A=",
   "message_token":4912661846655238145
}

Callback parameters

Name Description Possible values
event Callback type - which event triggered the callback unsubscribed
timestamp Time of the event that triggered the callback Epoch time
user_id Unique Viber user id  
message_token Unique ID of the message  

Conversation started

Conversation started event fires when a user opens a conversation with the bot using the “message” button (found on the account’s info screen) or using a deep link.

This event is not considered a subscribe event and doesn’t allow the account to send messages to the user; however, it will allow sending one “welcome message” to the user. See sending a welcome message below for more information.

Once a conversation_started callback is received, the Bot will be able to send a single “welcome message” sent as a regular send_message request. The receiver parameter is mandatory in this case.

Note: the conversation_started callback doesn’t contain the context parameter by default.

To add this paramater and determine its value, you can use a deeplink like this: viber://pa?chatURI=your_bot_URI&context=your_context

Callback data

{
   "event":"conversation_started",
   "timestamp":1457764197627,
   "message_token":4912661846655238145,
   "type":"open",
   "context":"context information",
   "user":{
      "id":"01234567890A=",
      "name":"John McClane",
      "avatar":"https://avatar.example.com",
      "country":"UK",
      "language":"en",
      "api_version":1
   },
   "subscribed":false
}

Callback parameters

Name Description Possible values
event Callback type - which event triggered the callback conversation_started
timestamp Time of the event that triggered the callback Epoch time
message_token Unique ID of the message  
type The specific type of conversation_started event open. Additional types may be added in the future
context Any additional parameters added to the deep link used to access the conversation passed as a string. See deep link section for additional information  
user.id Unique Viber user id  
user.name User’s Viber name  
user.avatar URL of user’s avatar  
user.country User’s 2 letter country code ISO ALPHA-2 Code
user.language User’s phone language  
user.api_version Max API version, matching the most updated user’s device  
subscribed indicated whether a user is already subscribed true if subscribed and false otherwise

Sending a welcome message

The Viber API allows sending messages to users only after they subscribe to the account. However, Viber allows the account to send a single “welcome message” to a user when the user initiates the conversation, before the user subscribed.

The welcome message will be sent as a regular message, following conversation_started callback, which will be received from Viber once the user opens the conversation with the account. To learn more about conversation_started event and its triggering conditions, please refer to Conversation started in the callbacks section of the documentation.

Welcome message flow

Sending a welcome message will be done according to the following flow:

  1. The user initiates a one-on-one conversation with the bot.
  2. The Viber server sends conversation_started event to bot’s webhook.
  3. The account receives the conversation_started event and should respond within 5 minutes by sending a message request to the send_message endpoint.

Message receipts callbacks

Viber offers message status updates for each message sent, allowing the account to be notified when the message was delivered to the user’s device (delivered status) and when the conversation containing the message was opened (seen status).

The seen callback will only be sent once when the user reads the unread messages, regardless of the number of messages sent to them, or the number of devices they are using.

If the message recipient is using their Viber account on multiple devices, each of the devices will return a delivered, meaning that several delivered callbacks can be received for a single message.

If Viber is unable to deliver the message to the client it will try to deliver it for up to 14 days. If the message wasn’t delivered within the 14 days it will not be delivered and no “delivered” or “seen” callbacks will be received for it.

Callback data

Delivered
{
   "event":"delivered",
   "timestamp":1457764197627,
   "message_token":4912661846655238145,
   "user_id":"01234567890A="
}
Seen
{
   "event":"seen",
   "timestamp":1457764197627,
   "message_token":4912661846655238145,
   "user_id":"01234567890A="
}

Callback parameters

Name Description Possible values
event Callback type - which event triggered the callback delivered, seen
timestamp Time of the event that triggered the callback Epoch time
message_token Unique ID of the message  
user_id Unique Viber user id  

Failed callback

The “failed” callback will be triggered if a message has reached the client but failed any of the client validations.

Since some of the message validations take place on the server while the others take place on the client, some messages may only fail after reaching the client. In such cases the flow will be as follows:

  1. Message is sent.
  2. Response with status 0 is received to indicate a successful request.
  3. The message reaches the client and fails client validation.
  4. “Failed” callback is sent to the webhook, containing the unique message token and a string explaining the failure.

Even though the verification fails, such messages can still be delivered to users and receive delivery statuses.

Callback data

{  
   "event":"failed",
   "timestamp":1457764197627,
   "message_token":4912661846655238145,
   "user_id":"01234567890A=",
   "desc":"failure description"
}

Callback parameters

Name Description Possible values
event Callback type - which event triggered the callback failed
timestamp Time of the event that triggered the callback Epoch time
message_token Unique ID of the message  
user_id Unique Viber user id  
desc A string describing the failure  

Receive message from user

The Chat API allows the user to send messages to the PA. Excluding file type, all message types are supported for sending from bot to user and from user to bot. These include: text, picture, video, contact, URL and location. The following callback data describes the structure of messages sent from user to PA.

Callback data

{
   "event":"message",
   "timestamp":1457764197627,
   "message_token":4912661846655238145,
   "sender":{
      "id":"01234567890A=",
      "name":"John McClane",
      "avatar":"https://avatar.example.com",
      "country":"UK",
      "language":"en",
      "api_version":1
   },
   "message":{
      "type":"text",
      "text":"a message to the service",
      "media":"https://example.com",
      "location":{
         "lat":50.76891,
         "lon":6.11499
      },
      "tracking_data":"tracking data"
   }
}

Callback general parameters

Name Description Possible values
event Callback type - which event triggered the callback message
timestamp Time of the event that triggered the callback Epoch time
message_token Unique ID of the message  
sender.id Unique Viber user id of the message sender  
sender.name Sender’s Viber name  
sender.avatar Sender’s avatar URL  
sender.country Sender’s 2 letter country code ISO ALPHA-2 Code
sender.language Sender’s phone language. Will be returned according to the device language ISO 639-1
sender.api_version The maximal Viber version that is supported by all of the user’s devices  
message Detailed in the chart below  

Callback message parameters

The callback message parameters depend on the type of message. For each message type, only the relevant parameters will be received.

Name Description Possible values
type Message type text, picture, video, file, sticker, contact, url and location
text The message text  
media URL of the message media - can be image, video, file and url. Image/Video/File URLs will have a TTL of 1 hour  
location Location coordinates lat & lon within valid ranges
contact name - contact’s username, phone_number - contact’s phone number and avatar as the avatar URL name - max 128 characters. Only one phone_number per contact can be sent
tracking_data Tracking data sent with the last message to the user  
file_name File name Relevant for file type messages
file_size File size in bytes Relevant for file type messages
duration Video length in milliseconds Relevant for video type messages
sticker_id Viber sticker id Relevant for sticker type messages

Message status

Once a 200 OK response is received from the PA, the message status will change to delivered on the user’s side. “Seen” status is not currently supported for messages sent from user to PA.

Error Codes

The following error codes will be returned with API responses. The status parameter will include the error code value while the status_message parameter will include the error name or a more specific string describing the error.

Value Name Description
0 ok Success
1 invalidUrl The webhook URL is not valid
2 invalidAuthToken The authentication token is not valid
3 badData There is an error in the request itself (missing comma, brackets, etc.)
4 missingData Some mandatory data is missing
5 receiverNotRegistered The receiver is not registered to Viber
6 receiverNotSubscribed The receiver is not subscribed to the account
7 publicAccountBlocked The account is blocked
8 publicAccountNotFound The account associated with the token is not a account.
9 publicAccountSuspended The account is suspended
10 webhookNotSet No webhook was set for the account
11 receiverNoSuitableDevice The receiver is using a device or a Viber version that don’t support accounts
12 tooManyRequests Rate control breach
13 apiVersionNotSupported Maximum supported account version by all user’s devices is less than the minApiVersion in the message
14 incompatibleWithVersion minApiVersion is not compatible to the message fields
15 publicAccountNotAuthorized The account is not authorized
16 inchatReplyMessageNotAllowed Inline message not allowed
17 publicAccountIsNotInline The account is not inline
18 noPublicChat Failed to post to public account. The bot is missing a Public Chat interface
19 cannotSendBroadcast Cannot send broadcast message
20 broadcastNotAllowed Attempt to send broadcast message from the bot
21 unsupportedCountry The message sent is not supported in the destination country
22 paymentUnsupported The bot does not support payment messages
23 freeMessagesExceeded The bot has reached the monthly threshold
24 noBalance No balance for a billable bot
other General error General error

Note: Failing to send the authentication token in the header will result in an error with the missing auth_token message.

Forbidden File Formats

Extension Format Operating system(s)
ACTION Automator Action Mac OS
APK Application Android
APP Executable Mac OS
BAT Batch File Windows
BIN Binary Executable Windows, Mac OS, Linux
CMD Command Script Windows
COM Command File Windows
COMMAND Terminal Command Mac OS
CPL Control Panel Extension Windows
CSH C Shell Script Mac OS, Linux
EXE Executable Windows
GADGET Windows Gadget Windows
INF1 Setup Information File Windows
INS Internet Communication Settings Windows
INX InstallShield Compiled Script Windows
IPA Application iOS
ISU InstallShield Uninstaller Script Windows
JOB Windows Task Scheduler Job File Windows
JSE JScript Encoded File Windows
KSH Unix Korn Shell Script Linux
LNK File Shortcut Windows
MSC Microsoft Common Console Document Windows
MSI Windows Installer Package Windows
MSP Windows Installer Patch Windows
MST Windows Installer Setup Transform File Windows
OSX Executable Mac OS
OUT Executable Linux
PAF Portable Application Installer File Windows
PIF Program Information File Windows
PRG Executable GEM
PS1 Windows PowerShell Cmdlet Windows
REG Registry Data File Windows
RGS Registry Script Windows
RUN Executable Linux
SCT Windows Scriptlet Windows
SHB Windows Document Shortcut Windows
SHS Shell Scrap Object Windows
U3P U3 Smart Application Windows
VB VBScript File Windows
VBE VBScript Encoded Script Windows
VBS VBScript File Windows
VBSCRIPT Visual Basic Script Windows
WORKFLOW Automator Workflow Mac OS
WS Windows Script Windows
WSF Windows Script Windows

Developers FAQ

Authentication Tokens

How do I get the account token?

Your token is generated and provided during the creation process. Once your bot is created, you will be added as an admin and the token will appear in your Viber account settings (More > Settings > Bots > Edit Info > Your app key)

Can the account token expire?

Tokens will not expire unless you request a new token from the Viber team.

Can I change the account token?

Yes, but only in very specific circumstances. If you believe your token has been compromised you may request a new one from the Viber Support team.

Webhooks

What happens if the webhook is not available?

When a webhook appears offline, Viber will retry the callback several times for an hour until the HTTP code 200 OK is received.

Can an account have more than one webhook?

Each account can have only one webhook.

Can more than one account use the same webhook?

The same webhook can be used for more than one account.

Why am I not getting callbacks to my webhook?

If you are not receiving callbacks to your webhook, please check the following:

  • Make sure the webhook is set correctly - use a get_account_info request to try it.
  • Check the token is available and live. Carry out any action and check that you receive the expected response.
  • Make sure that you’re testing the right actions to trigger a callback to the webhook - see Callbacks in the API for information about the different callbacks. Keep in mind that for some callbacks (delivered, seen) you may choose whether or not to receive them during the set_webhook request.
  • Check there are no errors or bugs on your side that prevent the webhook from properly receiving or displaying the callbacks.

Supported webhook certificates

The endpoint certificate authority should be on the Sun Java trusted root certificates list.

Account Subscribers

How do I get the user’s ID?

The user ID is available in all callbacks received from our server. Remember that a user must have subscribed to your account or sent you a message before you can message them.

Is the same user ID valid when sending messages from all accounts?

The user ID is unique per user and per account. This means that the same user will have a different user ID for each account of your they message.

Can the user ID change or expire?

User IDs do not change or expire. Each user has a unique ID when they communicate with an account. The ID won’t change unless the user activates Viber with a different number (as this will be a new Viber account). Keep in mind that the same user will have a different ID for each account.

Keyboards

What is the maximum size for a keyboard?

The maximum JSON for all API requests is 30kb. The keyboard can contain up to 12 rows in portrait mode. Learn more about Viber’s keyboard requirements here.

What happens if I send an invalid keyboard?

Most keyboard valuations take place on the client. If the request is successfully sent to the client and then fails one of the client validations you will receive a failed callback. The flow in this case is as follows:

  1. Message is sent.
  2. Response with status 0 is received to indicate a successful request.
  3. The message reaches the client and fails client validation.
  4. Failed callback is sent to the webhook, containing the unique message token and a string explaining the failure.

I sent a few keyboards, which one will the user see?

Viber will always display the last keyboard sent to the user.

General

What are bots?

Bots are Viber’s solution for partner brands and organizations to interact with users through Viber.

Read more about how to create a bot here.

Are there specific requirements for a bot?

Before you start using your bot, you must be able to demonstrate that it meets our requirements. Please check that your bot contains the following.

Bot details

  • The bot must comply with Viber’s naming and content policy (references to “Public Accounts” also apply to bots).
  • Your bot must adds unique value to Viber users
  • The details supplied when the bot was created are accurate and genuine
  • All details should display as intended
  • The bot’s functionality must be tested before you deploy it

Functionality

  • Bot behavior must be as stated in the account description
  • The bot should greet users who engage with it

Performance

  • Bot response time must be less than 5 seconds
  • If the response time is longer, there should be a message explaining this (for example: I’m processing your request, please wait)
  • The bot must be able to respond to all kinds of Viber message types (text, stickers, images, location and so on)
  • The bot should either recognize some forms of free text to continue the conversation, not include an input line (as explained in the API documentation)

Can I send messages based on users phone numbers?

Messages are sent to users based on user ID rather than phone number.

Messages are sent to users based on their user ID when they perform an action which triggers a callback.

Unique user IDs are created as a combination of user and account, so the same user may have more than one ID if they are contacting more than one of your accounts.


Viber API Access - White Paper

Viber 6.5 introduced a new Viber API, which third parties can use to send and receive messages between a bot and a Viber user.

Using the Viber API

Viber bots use the Viber Chat bot API and create a private encrypted communications channel between a bot and a subscribed Viber user. All information communicated over this channel can only be seen by the subscribed Viber user and the bot’s administrators. It cannot be accessed by any 3rd party API.

When creating a new bot you will receive an authentication token which is used for all communication with the Viber Back End. In order to enable communication between the Viber Back End and the account, the account must call the set webhook request with the authentication token. There is also an optional parameter (v6.5.1 and up) to define which events it will receive (such as delivered and seen notifications when clients receive and read messages). Once the set webhook request is received by the Viber Back End, it will validate the URL and send a response.

Communication between bots and Viber users

All communication between bots and Viber users can only be initialized by the Viber user starting a new conversation to the account (opt–in). When a Viber user subscribes to the bot, the account will receive the following information about the user:

  • id – Unique id used to identify and communicate with a specific Viber user.
  • name (optional) – Viber user name.
  • avatar (optional) – URL to the Viber profile picture of the user.
  • country – country code (ISO 3166–1 alpha–2).
  • language – user language (ISO 639–1).
  • api_version – version of chat api supported by client’s primary device (v6.5.1 and up).

Once a Viber user subscribes to a bot account, the bot can send messages to the Viber user freely (not only in response to a message from the user). Viber users can unsubscribe at any time from the bot, which will immediately block any further communication from the bot to the user. All messages will include a unique message token and timestamp created by the Viber Back End and will be synchronized between all users’ devices. Messages sent to the bot will also include the user’s Viber name and avatar.

Security

  • All Viber servers are hosted on a secure virtual private cloud (VPC) on AWS (Amazon Web Services).
  • All communication between the Viber Back End and the account is encrypted using HTTPS.
  • All communication between the Viber Back End and Viber clients is encrypted and is based on a proprietary TCP protocol.
  • Viber Back End verifies that the bot HTTPS SSL certificate was issued by an authorized CA (not self–signed or from an untrusted company).
  • All callbacks from Viber Back End sent to the account will include a signed signature that will allow the account to verify that the callback was created by Viber and was destined for this bot. The signature uses HMAC with SHA256 and uses the account token as the key and the callback JSON data as the value.
  • Viber reserves the option to use rate control for all Viber API calls.
  • Rakuten Viber service API endpoints will require a minimum TLS protocol level of TLS 1.2 or higher.

Privacy

  • Viber doesn’t use automatic content filtering on any incoming messages to users or outgoing messages from users to bots.
  • Viber does not store message content at all if both Viber user and account service are online.
  • Viber will save messages content in Viber Back End until a successful delivery to the destination.
  • If a Viber user chooses to disable the seen status in their privacy settings, then Viber will not send message status updates for seen by the user from the user to the account.
  • User ids sent to the bot are unique for each bot, meaning that the user id for a certain user received by account A will be different than the user id for the same user received by account B.

Successful delivery definition

  • For messages to a Viber user – The message is considered delivered once Viber on a device (primary or secondary) sends an ACK with a message token. If the user has multiple devices (primary and secondary) using the same Viber account, each of the devices will send an ACK for that message token. As a result of this logic, bots can receive more than one delivered or seen status update. For a specific user, Viber saves a message for up to 14 days or until the message is considered delivered to the user.
  • For messages from a Viber user to a bot – The message is considered delivered once the account service’s server responds with a 200 HTTP response code to the message sent to it. Viber Back End Viber API servers implement a limited retry mechanism to try to resend the message while the account service’s server is offline, but if the account service server is offline for a continuous amount of time, the message will not be delivered to the account.

TLS protocol level upgrade

Effective February 4, 2024, Rakuten Viber service API endpoints will require a minimum TLS protocol level of TLS 1.2 or higher. This update is crucial due to the deprecation of TLS 1.0 and 1.1 protocols, which are now considered insecure and vulnerable to attacks such as POODLE (Padding Oracle On Downgraded Legacy Encryption). This attack could potentially intercept and decrypt sensitive data over the internet. If your connections use TLS 1.2 or later, your service will not be affected. Modern client software applications built after 2014 using Java Development Kit (JDK) 8 or later, or other contemporary development environments, likely already support TLS 1.2 or later.

However, if you are using an older application version or have not upgraded your development environment since 2014, an update is likely necessary.

For partners still using TLS 1.0 or 1.1, updating your client software to support TLS 1.2 or later is essential to maintain connectivity. It’s important to note that you have control over the TLS version your client software uses. When connecting to Viber API endpoints, your client software negotiates its preferred TLS version, and Viber applies the highest mutually agreed-upon version.

Please follow the directions below to check your TLS version and prepare accordingly:

  • What is the most common use of TLS 1.0 or TLS 1.1?

The most common use of TLS 1.0 or 1.1 is found in .NET Framework versions earlier than 4.6.2. If you are using the .NET Framework, please verify that you are using version 4.6.2 or later.

  • What is Transport Layer Security (TLS)?

Transport Layer Security (TLS) is a cryptographic protocol that secures internet communications. Your client software can be configured to use TLS versions 1.0, 1.1, 1.2, or 1.3, or a subset of these when connecting to service endpoints. You must ensure that your client software supports TLS 1.2 or later.


Viber Developer Distribution Agreement or Viber API Terms of Service

Last updated: September 2021

Thank you for using the Viber application programming interfaces (the "Viber APIs"). As used herein, the terms "you" and "your" refer to each administrator, developer and user of the Viber APIs. You may also be referred to as Developer. By using the Viber APIs, you agree to these Terms of Service (the "Terms of Service") and the Viber Terms of Use (the "TOU"). If you use the Viber APIs as an interface to, or in conjunction with other Viber products or services, then the terms of those products or services will also apply. If you disagree with any of the terms below or the TOU, Viber does not grant you a license to use the Viber APIs. In the event of any inconsistency between these Terms of Service and the TOU, these Terms of Service control. Viber Media S.à r.l., its subsidiaries and affiliated companies (collectively, "Viber," "we," "our," or "us") reserve the right to update and change, from time to time, these Terms of Service and all documents incorporated by reference, and Viber may change these Terms of Service by posting a new version without notice to you. Use of the Viber APIs after such change constitutes acceptance of such change.

1. License Subject to the restrictions set forth in these Terms of Service, Viber grants you a non-exclusive, worldwide, personal, non-transferable, non-assignable, non-sublicensable, royalty-free license to use the Viber APIs. All rights not expressly granted to you are reserved by Viber.

2. Use of the Viber APIs.

  • You will comply with all applicable law, regulation, and third party rights (including without limitation laws regarding the import or export of data or software, privacy, and local laws). You will not use the Viber APIs to encourage or promote illegal activity or violation of third party rights. You will not violate any other terms of use or agreements with Viber.
  • You will only access (or attempt to access) the Viber APIs by the means described in the documentation of that API. If Viber assigns you developer credentials (e.g. client IDs), you must use them with the applicable Viber APIs. You will not misrepresent or mask either your identity or your API Client's identity when using the Viber APIs or developer accounts.
  • Viber may set and enforce limits on your use of the Viber APIs (e.g. limiting the number of API requests that you may make or the number of users you may serve) in our sole discretion. You agree to and will not attempt to circumvent such limitations. If you would like to use any Viber API beyond the applicable limits, you must obtain our express consent (and we may decline such request or condition acceptance on your agreement to additional terms and/or charges for that use).

3. API Clients and Monitoring. The Viber APIs are designed to help you enhance your websites and applications ("API Client(s)"). Viber is not required to promote or recommend your API Client. YOU AGREE THAT VIBER MAY MONITOR USE OF THE APIS TO ENSURE QUALITY, IMPROVE VIBER PRODUCTS AND SERVICES, AND VERIFY YOUR COMPLIANCE WITH THE TERMS OF SERVICE. This monitoring may include Viber accessing and using your API Client, for example, to identify security issues that could affect Viber or its users. You will not interfere with this monitoring. Viber may use any technical means to overcome such interference. Viber may suspend access to the Viber APIs by you or your API Client without notice if we reasonably believe that you are in violation f the Terms of Service or the TOU.

4. Security. You will use best commercial efforts to protect user information collected by your API Client, including personally identifiable information ("PII"), from unauthorized access or use and will promptly report to your users and any other party as required by applicable law any unauthorized access or use of such information to the extent required by applicable law.

5. User Privacy and API Clients. You will comply with all applicable privacy laws and regulations including those applying to PII. You will provide and adhere to a privacy policy for your API Client that clearly and accurately describes to users of your API Client what user information you collect and how you use and share such information (including for advertising) with Viber and third parties. You agree that you are the controller of any EU Personal Data (as defined in Exhibit A hereto) of end users collected by you, and Viber is a controller of any EU Personal Data of end users collected by it, and, you agree that you will be regarded as business with respect to any U.S. Personal Information (as defined in Exhibit A hereto) of end users collected by you, and Viber will be regarded as business with respect to any U.S. Personal Information of end users collected by it., and you further agree to the terms of the Data Processing Addendum attached as Exhibit A hereto in connection with any EU Personal Data and/or U.S. Personal Information transferred between the Parties in connection with your use of the Viber API. You represent that you will not request the Viber API Personal Data (as defined in Exhibit A hereto) of users which you do not have a legal basis to process.

6. Viber API Prohibitions. When using the Viber APIs, you may not (or allow those acting on your behalf to):

  • Perform an action with the intent of introducing to Viber products and services any viruses, worms, defects, Trojan horses, malware, or any items of a destructive nature.
  • Defame, abuse, harass, stalk, or threaten others.
  • Interfere with or disrupt the Viber APIs or the servers or networks providing the Viber APIs.
  • Promote or facilitate unlawful online gambling or disruptive commercial messages or advertisements.
  • Reverse engineer or attempt to extract the source code from any Viber API or any related software, except to the extent that this restriction is expressly prohibited by applicable law.
  • Use the Viber APIs for any activities where the use or failure of the Viber APIs could lead to death, personal injury, or environmental damage (such as the operation of nuclear facilities, air traffic control, or life support systems).
  • Use the Viber APIs to process or store any data that is subject to the International Traffic in Arms Regulations maintained by the U.S. Department of State.
  • Remove, obscure, or alter any Viber Terms of Service or any links to or notices of those terms.

Viber reserves the right to charge fees for future use of or access to the Viber APIs in Viber's sole discretion. If Viber decides to charge for use of the Viber APIs, such charges will be disclosed to you prior to their effect. Viber also reserves the right to include advertising in or associated with any information provided to you through the Viber APIs.

7. Confidential Information.

  • Developer credentials (such as passwords, keys, and client IDs) are intended to be used by you and to identify your API Client. You will keep your credentials confidential and make reasonable efforts to prevent and discourage other API Clients from using your credentials. Developer credentials may not be embedded in open source projects.
  • Our communications to you and the Viber APIs may contain Viber confidential information. Viber confidential information includes any materials, communications, and information that are marked confidential or that would normally be considered confidential under the circumstances. If you receive any such information, then you will not disclose it to any third party without Viber's prior written consent. Viber confidential information does not include information that you independently developed, that was rightfully given to you by a third party without confidentiality obligation, or that becomes public through no fault of your own. You may disclose Viber confidential information when compelled to do so by law if you provide us reasonable prior notice. If you have entered a specific Non Disclosure Agreement with Viber, such Non Disclosure Agreement shall prevail over the confidentiality obligations set forth in this Section 7(b).

8. Ownership. The Viber APIs may be protected by copyrights, trademarks, service marks, international treaties, and/or other proprietary rights and laws of the U.S. and other countries. Viber's rights apply to the Viber APIs and all output and executables of the Viber APIs, excluding any software components developed by you which do not themselves incorporate the Viber APIs or any output or executables of such software components. You agree to abide by all applicable proprietary rights laws and other laws including without limitation the laws of the United States of America and all other countries where you use the Viber APIs, as well as any additional copyright notices or restrictions contained in these Terms of Service. Viber owns all rights, title, and interest in and to the Viber APIs. These Terms of Service grant you no right, title, or interest in any intellectual property owned or licensed by Viber, including (but not limited to) the Viber APIs.

9. Termination. You may stop using the Viber APIs at any time with or without notice. Further, if you want to terminate the Terms of Service, you must provide Viber with prior written notice and upon termination, cease your use of the Viber APIs. Viber reserves the right to terminate the Terms of Service with you without notice, liability, or other obligation to you.

10. Support. Viber may elect to provide you with support or modifications for the Viber APIs (collectively, "Support"), in its sole discretion, and may terminate such Support at any time without notice to you. Viber may change, suspend, or discontinue any aspect of the Viber APIs for any reason at any time, including the availability of any Viber APIs. Viber may also impose limits on certain features and services or restrict your access to parts or all of the Viber APIs without notice or liability.

11. Your Obligations Post-Termination. Upon any termination of the Terms of Service or discontinuation of your access to the Viber APIs, you will immediately stop using the Viber APIs, and upon Viber's written request, delete and/or return to us, any Viber confidential information. Viber may independently communicate with any account owner whose account(s) are associated with your API Client and developer credentials to provide notice of the termination of your right to use the Viber APIs.

12. Survival clause. When the Terms of Service terminate, those terms that by their nature are intended to continue indefinitely will continue to apply.

13. Disclaimer of Warranty. SOME OF THE VIBER APIS ARE EXPERIMENTAL AND HAVE NOT BEEN TESTED IN ANY MANNER. VIBER DOES NOT REPRESENT OR WARRANT THAT VIBER APIS ARE FREE OF INACCURACIES, ERRORS, BUGS, OR INTERRUPTIONS, OR ARE RELIABLE, ACCURATE, COMPLETE, OR OTHERWISE VALID. TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE VIBER APIS ARE PROVIDED "AS IS" WITH NO WARRANTY, EXPRESS OR IMPLIED, OF ANY KIND AND VIBER EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AVAILABILITY, SECURITY, TITLE AND/OR NON-INFRINGEMENT. YOUR USE OF THE VIBER APIS IS AT YOUR OWN DISCRETION AND RISK, AND YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE THAT RESULTS FROM THE USE OF THE VIBER APIS INCLUDING, BUT NOT LIMITED TO, ANY DAMAGE TO YOUR COMPUTER SYSTEM OR LOSS OF DATA.

14. Limitation of Liability. TO THE EXTENT PERMITTED BY APPLICABLE LAW, VIBER SHALL NOT, UNDER ANY CIRCUMSTANCES, BE LIABLE TO YOU FOR ANY DIRECT, INDIRECT, PUNITIVE, ACTUAL, INCIDENTAL, CONSEQUENTIAL, SPECIAL OR EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH ANY USE, OR INABILITY TO USE, THE VIBER APIS, WHETHER BASED ON BREACH OF CONTRACT, BREACH OF WARRANTY, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, OR ANY OTHER PECUNIARY LOSS, REGARDLESS OF THE BASIS UPON WHICH LIABILITY IS CLAIMED AND WHETHER OR NOT VIBER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGES. UNDER NO CIRCUMSTANCES SHALL VIBER BE LIABLE TO YOU FOR ANY AMOUNT. WITHOUT LIMITATION, YOU (AND NOT VIBER) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVING, REPAIR, OR CORRECTION IN THE EVENT OF ANY SUCH LOSS OR DAMAGE ARISING THEREIN. IF APPLICABLE LAW DOES NOT ALLOW ALL OR ANY PART OF THE ABOVE LIMITATION OF LIABILITY TO APPLY TO YOU, THE LIMITATIONS WILL APPLY TO YOU ONLY TO THE EXTENT PERMITTED BY APPLICABLE LAW. In no event shall Viber's total liability to you for all damages (other than as may be required by applicable law in cases involving personal injury) exceed the amount of fifty U.S. dollars ($50.00). The foregoing limitations will apply even if the above stated remedy fails of its essential purpose.

15. Indemnification. To the maximum extent permitted by applicable law, you agree to hold harmless and indemnify Viber and its subsidiaries, affiliates, officers, agents, licensors, co-branders or other partners, and employees from and against any third party claims arising from or in any way related to your use of the Viber APIs, including any liability or expense arising from all claims, losses, damages (actual and/or consequential), suits, judgments, litigation costs and attorneys' fees, of every kind and nature. Viber shall use good faith efforts to provide you with written notice of such claim, suit or action.

16. Relationship of the Parties. Notwithstanding any provision hereof, for all purposes of the Terms of Service, you and Viber shall be and act independently and not as partner, joint venturer, agent, employee or employer of the other. You shall not have any authority to assume or create any obligation for or on behalf of Viber, express or implied, and you shall not attempt to bind Viber to any contract.

17. Invalidity of Specific Terms. If any provision of these Terms of Service is adjudged, by written decision, to be unlawful, void, or for any reason unenforceable, then that provision shall be deemed severable from this agreement and shall not affect the validity and enforceability of any remaining provisions.

18. Choice of Law. To the extent permitted by law, the Terms of Service and any provisions therein shall be governed by, construed and enforced in accordance with the laws of the State of New York, as they are applied to agreements entered into and to be performed entirely within New York.

19. No Waiver of Rights by Viber. Viber's failure to exercise or enforce any right or provision of the Terms of Service shall not constitute a waiver of such right or provision.

20. Miscellaneous. The section headings and subheadings contained in this agreement are included for convenience only, and shall not limit or otherwise affect the terms of the Terms of Service. Any construction or interpretation to be made of the Terms of Service shall not be construed against the drafter. The Terms of Service, the Viber Terms of Use and any other applicable Viber product or service terms, constitute the entire agreement between Viber and you with respect to the subject matter hereof.

Exhibit A

General Data Protection Addendum to the Viber API Terms of Service

This Addendum to the Viber API Terms of Service (the "Agreement") is by and between Viber Media S.a.r.l, a Luxembourg limited liability company ("Viber"), and Developer having selected to use the Viber API under the Agreement. Viber and Developer are each a "Party" and collectively the "Parties." This Addendum is an integral part of the Agreement. Any words or terms not otherwise defined in this Addendum have the same meaning as in the Agreement. In the event of a conflict between definitions in the Agreement and this Addendum, the definitions within this Addendum control.

1. Definitions.

(a) " Personal Data," " Process/Processing, " Controller", " Processor," " Data Subject" and " Supervisory Authority shall have the same meanings given to them in the Regulation (or where the same or similar terms are used under another applicable Data Protection Law, the meanings given to such terms under such Data Protection Law).

(b) " EU Personal Data" means personal data of natural persons subject to the Regulation.

(c) " U.S. Personal Information" means any information that relates to, is capable of being associated with, or could be linked, directly or indirectly, with a particular United States resident or household.

(d) "Data Protection Law(s)" means privacy or data protection laws that apply to data transferred by each of the Parties to the other, including, but not limited to, the Regulation, any successor thereto, and the California Consumer Privacy Act.

(e) " Directive" means the Directive 95/46/EC of the European Parliament and of the Council (Personal Data Directive).

(f) " Regulation" means Regulation (EU) 2016/679 of the European Parliament and the Council (General Data Protection Regulation).

2. Role of the Parties. In order to provide the Services under the Agreement, Viber discloses data, including EU Personal Data and/or U.S. Personal Information to Developer solely for the purposes described in the Agreement (the "Permitted Purposes") and Viber is a Controller of the EU Personal Data, and business with respect to any U.S. Personal Information, it discloses to Developer. Pursuant to the Agreement, Developer uses the data as a separate and independent Controller or Business for the Permitted Purposes. In no event will the Parties process the data as joint Controllers.

3. Obligations.

a. Each Party shall use the Personal Data in accordance with the Regulation and other applicable Data Protection Laws, will not cause the other Party to breach its obligations under Data Protection Laws and will individually and separately fulfill all obligations that apply to it as a Controller under the Regulation or Business under the California Consumer Privacy Act.

The Developer shall use the Personal Data it receives from the Viber only for the Permitted Purposes in line with the Agreement and this Addendum, unless otherwise required by applicable laws.

b. In order to disclose Personal Data to for the Permitted Purposes and in compliance with the Regulation and other applicable Data Protection Laws, each Party's obligations include without limitation: (i) identifying and establishing its independent legal basis for processing and disclosing Personal Data; and (ii) fulfilling transparency requirements regarding its use of and disclosure of Personal Data.

c. The Developer will assure it obtains the necessary right(s) from Data Subjects to request Personal Data from Viber pursuant to the Agreement for the Permitted Purposes.

4. International Data Transfers.

a. The Parties acknowledge that in the course of their cooperation under the Agreement, E.U. Personal Data may be transferred internationally. In all cases where Personal Data is transferred internationally to a country not providing adequate Personal Data protection in accordance with applicable Data Protection Laws, the Parties will ensure that appropriate safeguards that ensure a level of data protection of Personal Data essentially similar to that provided under applicable Data Protection Laws and this Addendum are put in place.

b. The obligations herein shall apply inter alia to any onward transfer to another third country; or to another entity within the same country it has been exported to.

c. Further restrictions on data exports from the European Economic Area (" EEA"):

  1. For any Personal Data originating in the EEA, Developer agrees to comply with the C-to-C Transfer Clauses set forth by the European Commission in the form attached as Schedule 1 hereto.
  2. In the event that the C-to-C Transfer Clauses are amended, replaced or repealed by the European Commission or under applicable Data Protection Laws, the Parties shall enter into an updated version of the C-to-C Transfer Clauses.

5. This Addendum shall survive termination or expiration of the Agreement. Upon termination or expiration of the Agreement, the Developer may only continue to process Personal Data received from Viber provided if such use complies the requirements of this Addendum and under the Regulation.

Schedule 1 to the Addendum

C-to-C Standard Contractual Clauses for the transfer of personal data to third countries pursuant to Regulation (EU) 2016/679 in accordance with Commission Implementing Decision (EU) 2021/914 of 4 June 2021

MODULE ONE: Transfer controller to controller

These C-to-C Standard Contractual Clauses for the transfer of personal from the European Economic Area community to third countries data transfer agreement between Viber Media S.a.r.l ("Viber") and the Developer which is making use of the Viber API according to the Viber API Terms of Service. For the purposes of these C-to-C Standard Contractual Clauses, Viber is the data exporter and Developer is the data importer. Developer and Viber are each a "Party" and collectively the "Parties".

SECTION I

Clause 1 – Purpose and scope

(a) The purpose of these standard contractual clauses is to ensure compliance with the requirements of Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016 on the protection of natural persons with regard to the processing of personal data and on the free movement of such data (General Data Protection Regulation) for the transfer of personal data to a third country.

(b) The Parties have agreed to these standard contractual clauses (hereinafter: ' Clauses' ).

(c) These Clauses apply with respect to the transfer of personal data as specified in Annex I.B.

(d) The Appendix to these Clauses containing the Annexes referred to therein forms an integral part of these Clauses.

Clause 2 – Effect and invariability of the Clauses

(a) These Clauses set out appropriate safeguards, including enforceable data subject rights and effective legal remedies, pursuant to Article 46(1) and Article 46(2)(c) of Regulation (EU) 2016/679 and, with respect to data transfers from controllers to processors and/or processors to processors, standard contractual clauses pursuant to Article 28(7) of Regulation (EU) 2016/679, provided they are not modified, except to select the appropriate Module(s) or to add or update information in the Appendix. This does not prevent the Parties from including the standard contractual clauses laid down in these Clauses in a wider contract and/or to add other clauses or additional safeguards, provided that they do not contradict, directly or indirectly, these Clauses or prejudice the fundamental rights or freedoms of data subjects.

(b) These Clauses are without prejudice to obligations to which the data exporter is subject by virtue of Regulation (EU) 2016/679.

Clause 3 – Third-party beneficiaries

(a) Data subjects may invoke and enforce these Clauses, as third-party beneficiaries, against the data exporter and/or data importer, with the following exceptions:

(i) Clause 1, Clause 2, Clause 3, Clause 6, Clause 7;

(ii) Clause 8 – Clause 8.5 (e) and Clause 8.9(b);

(iii) Clause 12 – Clause 12(a) and (d);

(iv) Clause 13;

(v) Clause 15.1(c), (d) and (e);

(vi) Clause 16(e);

(vii) Clause 18 – Clause 18(a) and (b).

(b) Paragraph (a) is without prejudice to rights of data subjects under Regulation (EU) 2016/679.

Clause 4 – Interpretation

(a) Where these Clauses use terms that are defined in Regulation (EU) 2016/679, those terms shall have the same meaning as in that Regulation.

(b) These Clauses shall be read and interpreted in the light of the provisions of Regulation (EU) 2016/679.

(c) These Clauses shall not be interpreted in a way that conflicts with rights and obligations provided for in Regulation (EU) 2016/679.

Clause 5 – Hierarchy

In the event of a contradiction between these Clauses and the provisions of related agreements between the Parties, existing at the time these Clauses are agreed or entered into thereafter, these Clauses shall prevail.

Clause 6 – Description of the transfer(s)

The details of the transfer(s), and in particular the categories of personal data that are transferred and the purpose(s) for which they are transferred, are specified in Annex I.B.

SECTION II – OBLIGATIONS OF THE PARTIES

Clause 8 – Data protection safeguards

The data exporter warrants that it has used reasonable efforts to determine that the data importer is able, through the implementation of appropriate technical and organisational measures, to satisfy its obligations under these Clauses.

8.1 Purpose limitation

The data importer shall process the personal data only for the specific purpose(s) of the transfer, as set out in Annex I.B. It may only process the personal data for another purpose:

(i) where it has obtained the data subject's prior consent;

(ii) where necessary for the establishment, exercise or defence of legal claims in the context of specific administrative, regulatory or judicial proceedings; or

(iii) where necessary in order to protect the vital interests of the data subject or of another natural person.

8.2 Transparency

(a) In order to enable data subjects to effectively exercise their rights pursuant to Clause 10, the data importer shall inform them, either directly or through the data exporter:

(i) of its identity and contact details;

(ii) of the categories of personal data processed;

(iii) of the right to obtain a copy of these Clauses;

(iv) where it intends to onward transfer the personal data to any third party/ies, of the recipient or categories of recipients (as appropriate with a view to providing meaningful information), the purpose of such onward transfer and the ground therefore pursuant to Clause 8.7.

(b) Paragraph (a) shall not apply where the data subject already has the information, including when such information has already been provided by the data exporter, or providing the information proves impossible or would involve a disproportionate effort for the data importer. In the latter case, the data importer shall, to the extent possible, make the information publicly available.

(c) On request, the Parties shall make a copy of these Clauses, including the Appendix as completed by them, available to the data subject free of charge. To the extent necessary to protect business secrets or other confidential information, including personal data, the Parties may redact part of the text of the Appendix prior to sharing a copy, but shall provide a meaningful summary where the data subject would otherwise not be able to understand its content or exercise his/her rights. On request, the Parties shall provide the data subject with the reasons for the redactions, to the extent possible without revealing the redacted information.

(d) Paragraphs (a) to (c) are without prejudice to the obligations of the data exporter under Articles 13 and 14 of Regulation (EU) 2016/679.

8.3 Accuracy and data minimisation

(a) Each Party shall ensure that the personal data is accurate and, where necessary, kept up to date. The data importer shall take every reasonable step to ensure that personal data that is inaccurate, having regard to the purpose(s) of processing, is erased or rectified without delay.

(b) If one of the Parties becomes aware that the personal data it has transferred or received is inaccurate, or has become outdated, it shall inform the other Party without undue delay.

(c) The data importer shall ensure that the personal data is adequate, relevant and limited to what is necessary in relation to the purpose(s) of processing.

8.4 Storage limitation

The data importer shall retain the personal data for no longer than necessary for the purpose(s) for which it is processed. It shall put in place appropriate technical or organisational measures to ensure compliance with this obligation, including erasure or anonymisation of the data and all back-ups at the end of the retention period.

8.5 Security of processing

(a) The data importer and, during transmission, also the data exporter shall implement appropriate technical and organisational measures to ensure the security of the personal data, including protection against a breach of security leading to accidental or unlawful destruction, loss, alteration, unauthorised disclosure or access (hereinafter ' personal data breach'). In assessing the appropriate level of security, they shall take due account of the state of the art, the costs of implementation, the nature, scope, context and purpose(s) of processing and the risks involved in the processing for the data subject. The Parties shall in particular consider having recourse to encryption or pseudonymisation, including during transmission, where the purpose of processing can be fulfilled in that manner.

(b) The Parties have agreed on the technical and organisational measures set out in Annex II. The data importer shall carry out regular checks to ensure that these measures continue to provide an appropriate level of security.

(c) The data importer shall ensure that persons authorised to process the personal data have committed themselves to confidentiality or are under an appropriate statutory obligation of confidentiality.

(d) In the event of a personal data breach concerning personal data processed by the data importer under these Clauses, the data importer shall take appropriate measures to address the personal data breach, including measures to mitigate its possible adverse effects.

(e) In case of a personal data breach that is likely to result in a risk to the rights and freedoms of natural persons, the data importer shall without undue delay notify both the data exporter and the competent supervisory authority pursuant to Clause 13. Such notification shall contain i) a description of the nature of the breach (including, where possible, categories and approximate number of data subjects and personal data records concerned), ii) its likely consequences, iii) the measures taken or proposed to address the breach, and iv) the details of a contact point from whom more information can be obtained. To the extent it is not possible for the data importer to provide all the information at the same time, it may do so in phases without undue further delay.

(f) In case of a personal data breach that is likely to result in a high risk to the rights and freedoms of natural persons, the data importer shall also notify without undue delay the data subjects concerned of the personal data breach and its nature, if necessary in cooperation with the data exporter, together with the information referred to in paragraph (e), points ii) to iv), unless the data importer has implemented measures to significantly reduce the risk to the rights or freedoms of natural persons, or notification would involve disproportionate efforts. In the latter case, the data importer shall instead issue a public communication or take a similar measure to inform the public of the personal data breach.

(g) The data importer shall document all relevant facts relating to the personal data breach, including its effects and any remedial action taken, and keep a record thereof.

8.6 Sensitive data

Where the transfer involves personal data revealing racial or ethnic origin, political opinions, religious or philosophical beliefs, or trade union membership, genetic data, or biometric data for the purpose of uniquely identifying a natural person, data concerning health or a person's sex life or sexual orientation, or data relating to criminal convictions or offences (hereinafter ' sensitive data'), the data importer shall apply specific restrictions and/or additional safeguards adapted to the specific nature of the data and the risks involved. This may include restricting the personnel permitted to access the personal data, additional security measures (such as pseudonymisation) and/or additional restrictions with respect to further disclosure.

8.7 Onward transfers

The data importer shall not disclose the personal data to a third party located outside the European Union (in the same country as the data importer or in another third country, hereinafter ' onward transfer') unless the third party is or agrees to be bound by these Clauses, under the appropriate Module. Otherwise, an onward transfer by the data importer may only take place if:

(i) it is to a country benefitting from an adequacy decision pursuant to Article 45 of Regulation (EU) 2016/679 that covers the onward transfer;

(ii) the third party otherwise ensures appropriate safeguards pursuant to Articles 46 or 47 of Regulation (EU) 2016/679 with respect to the processing in question;

(iii) the third party enters into a binding instrument with the data importer ensuring the same level of data protection as under these Clauses, and the data importer provides a copy of these safeguards to the data exporter;

(iv) it is necessary for the establishment, exercise or defence of legal claims in the context of specific administrative, regulatory or judicial proceedings;

(v) it is necessary in order to protect the vital interests of the data subject or of another natural person; or

(vi) where none of the other conditions apply, the data importer has obtained the explicit consent of the data subject for an onward transfer in a specific situation, after having informed him/her of its purpose(s), the identity of the recipient and the possible risks of such transfer to him/her due to the lack of appropriate data protection safeguards. In this case, the data importer shall inform the data exporter and, at the request of the latter, shall transmit to it a copy of the information provided to the data subject.

Any onward transfer is subject to compliance by the data importer with all the other safeguards under these Clauses, in particular purpose limitation.

8.8 Processing under the authority of the data importer

The data importer shall ensure that any person acting under its authority, including a processor, processes the data only on its instructions.

8.9 Documentation and compliance

(a) Each Party shall be able to demonstrate compliance with its obligations under these Clauses. In particular, the data importer shall keep appropriate documentation of the processing activities carried out under its responsibility. (b) The data importer shall make such documentation available to the competent supervisory authority on request.

Clause 9 – Use of sub-processors

[Not applicable]

Clause 10 – Data subject rights

(a) The data importer, where relevant with the assistance of the data exporter, shall deal with any enquiries and requests it receives from a data subject relating to the processing of his/her personal data and the exercise of his/her rights under these Clauses without undue delay and at the latest within one month of the receipt of the enquiry or request. The data importer shall take appropriate measures to facilitate such enquiries, requests and the exercise of data subject rights. Any information provided to the data subject shall be in an intelligible and easily accessible form, using clear and plain language.

(b) In particular, upon request by the data subject the data importer shall, free of charge:

(i) provide confirmation to the data subject as to whether personal data concerning him/her is being processed and, where this is the case, a copy of the data relating to him/her and the information in Annex I; if personal data has been or will be onward transferred, provide information on recipients or categories of recipients (as appropriate with a view to providing meaningful information) to which the personal data has been or will be onward transferred, the purpose of such onward transfers and their ground pursuant to Clause 8.7; and provide information on the right to lodge a complaint with a supervisory authority in accordance with Clause 12(c)(i);

(ii) rectify inaccurate or incomplete data concerning the data subject;

(iii) erase personal data concerning the data subject if such data is being or has been processed in violation of any of these Clauses ensuring third-party beneficiary rights, or if the data subject withdraws the consent on which the processing is based.

(c) Where the data importer processes the personal data for direct marketing purposes, it shall cease processing for such purposes if the data subject objects to it.

(d) The data importer shall not make a decision based solely on the automated processing of the personal data transferred (hereinafter ' automated decision'), which would produce legal effects concerning the data subject or similarly significantly affect him/her, unless with the explicit consent of the data subject or if authorised to do so under the laws of the country of destination, provided that such laws lays down suitable measures to safeguard the data subject's rights and legitimate interests. In this case, the data importer shall, where necessary in cooperation with the data exporter:

(i) inform the data subject about the envisaged automated decision, the envisaged consequences and the logic involved; and

(ii) implement suitable safeguards, at least by enabling the data subject to contest the decision, express his/her point of view and obtain review by a human being.

(e) Where requests from a data subject are excessive, in particular because of their repetitive character, the data importer may either charge a reasonable fee taking into account the administrative costs of granting the request or refuse to act on the request.

(f) The data importer may refuse a data subject's request if such refusal is allowed under the laws of the country of destination and is necessary and proportionate in a democratic society to protect one of the objectives listed in Article 23(1) of Regulation (EU) 2016/679.

(g) If the data importer intends to refuse a data subject's request, it shall inform the data subject of the reasons for the refusal and the possibility of lodging a complaint with the competent supervisory authority and/or seeking judicial redress.

Clause 11 – Redress

(a) The data importer shall inform data subjects in a transparent and easily accessible format, through individual notice or on its website, of a contact point authorised to handle complaints. It shall deal promptly with any complaints it receives from a data subject.

(b) In case of a dispute between a data subject and one of the Parties as regards compliance with these Clauses, that Party shall use its best efforts to resolve the issue amicably in a timely fashion. The Parties shall keep each other informed about such disputes and, where appropriate, cooperate in resolving them.

(c) Where the data subject invokes a third-party beneficiary right pursuant to Clause 3, the data importer shall accept the decision of the data subject to:

(i) lodge a complaint with the supervisory authority in the Member State of his/her habitual residence or place of work, or the competent supervisory authority pursuant to Clause 13;

(ii) refer the dispute to the competent courts within the meaning of Clause 18.

(d) The Parties accept that the data subject may be represented by a not-for-profit body, organisation or association under the conditions set out in Article 80(1) of Regulation (EU) 2016/679.

(e) The data importer shall abide by a decision that is binding under the applicable EU or Member State law.

(f) The data importer agrees that the choice made by the data subject will not prejudice his/her substantive and procedural rights to seek remedies in accordance with applicable laws.

Clause 12 – Liability

(a) Each Party shall be liable to the other Party/ies for any damages it causes the other Party/ies by any breach of these Clauses.

(b) Each Party shall be liable to the data subject, and the data subject shall be entitled to receive compensation, for any material or non-material damages that the Party causes the data subject by breaching the third-party beneficiary rights under these Clauses. This is without prejudice to the liability of the data exporter under Regulation (EU) 2016/679.

(c) Where more than one Party is responsible for any damage caused to the data subject as a result of a breach of these Clauses, all responsible Parties shall be jointly and severally liable and the data subject is entitled to bring an action in court against any of these Parties.

(d) The Parties agree that if one Party is held liable under paragraph (c), it shall be entitled to claim back from the other Party/ies that part of the compensation corresponding to its/their responsibility for the damage.

(e) The data importer may not invoke the conduct of a processor or sub-processor to avoid its own liability.

Clause 13 – Supervision

(a) The supervisory authority with responsibility for ensuring compliance by the data exporter with Regulation (EU) 2016/679 as regards the data transfer, as indicated in Annex I.C, shall act as competent supervisory authority.

(b) The data importer agrees to submit itself to the jurisdiction of and cooperate with the competent supervisory authority in any procedures aimed at ensuring compliance with these Clauses. In particular, the data importer agrees to respond to enquiries, submit to audits and comply with the measures adopted by the supervisory authority, including remedial and compensatory measures. It shall provide the supervisory authority with written confirmation that the necessary actions have been taken.

SECTION III – LOCAL LAWS AND OBLIGATIONS IN CASE OF ACCESS BY PUBLIC AUTHORITIES

Clause 14 – Local laws and practices affecting compliance with the Clauses

(a) The Parties warrant that they have no reason to believe that the laws and practices in the third country of destination applicable to the processing of the personal data by the data importer, including any requirements to disclose personal data or measures authorising access by public authorities, prevent the data importer from fulfilling its obligations under these Clauses. This is based on the understanding that laws and practices that respect the essence of the fundamental rights and freedoms and do not exceed what is necessary and proportionate in a democratic society to safeguard one of the objectives listed in Article 23(1) of Regulation (EU) 2016/679, are not in contradiction with these Clauses.

(b) The Parties declare that in providing the warranty in paragraph (a), they have taken due account in particular of the following elements:

(i) the specific circumstances of the transfer, including the length of the processing chain, the number of actors involved and the transmission channels used; intended onward transfers; the type of recipient; the purpose of processing; the categories and format of the transferred personal data; the economic sector in which the transfer occurs; the storage location of the data transferred;

(ii) the laws and practices of the third country of destination– including those requiring the disclosure of data to public authorities or authorising access by such authorities – relevant in light of the specific circumstances of the transfer, and the applicable limitations and safeguards;

(iii) any relevant contractual, technical or organisational safeguards put in place to supplement the safeguards under these Clauses, including measures applied during transmission and to the processing of the personal data in the country of destination.

(c) The data importer warrants that, in carrying out the assessment under paragraph (b), it has made its best efforts to provide the data exporter with relevant information and agrees that it will continue to cooperate with the data exporter in ensuring compliance with these Clauses.

(d) The Parties agree to document the assessment under paragraph (b) and make it available to the competent supervisory authority on request.

(e) The data importer agrees to notify the data exporter promptly if, after having agreed to these Clauses and for the duration of the contract, it has reason to believe that it is or has become subject to laws or practices not in line with the requirements under paragraph (a), including following a change in the laws of the third country or a measure (such as a disclosure request) indicating an application of such laws in practice that is not in line with the requirements in paragraph (a).

(f) Following a notification pursuant to paragraph (e), or if the data exporter otherwise has reason to believe that the data importer can no longer fulfil its obligations under these Clauses, the data exporter shall promptly identify appropriate measures (e.g. technical or organisational measures to ensure security and confidentiality) to be adopted by the data exporter and/or data importer to address the situation. The data exporter shall suspend the data transfer if it considers that no appropriate safeguards for such transfer can be ensured, or if instructed by the competent supervisory authority to do so. In this case, the data exporter shall be entitled to terminate the contract, insofar as it concerns the processing of personal data under these Clauses. If the contract involves more than two Parties, the data exporter may exercise this right to termination only with respect to the relevant Party, unless the Parties have agreed otherwise. Where the contract is terminated pursuant to this Clause, Clause 16(d) and (e) shall apply.

Clause 15 – Obligations of the data importer in case of access by public authorities

15.1 Notification

(a) The data importer agrees to notify the data exporter and, where possible, the data subject promptly (if necessary with the help of the data exporter) if it:

(i) receives a legally binding request from a public authority, including judicial authorities, under the laws of the country of destination for the disclosure of personal data transferred pursuant to these Clauses; such notification shall include information about the personal data requested, the requesting authority, the legal basis for the request and the response provided; or

(ii) becomes aware of any direct access by public authorities to personal data transferred pursuant to these Clauses in accordance with the laws of the country of destination; such notification shall include all information available to the importer.

(b) If the data importer is prohibited from notifying the data exporter and/or the data subject under the laws of the country of destination, the data importer agrees to use its best efforts to obtain a waiver of the prohibition, with a view to communicating as much information as possible, as soon as possible. The data importer agrees to document its best efforts in order to be able to demonstrate them on request of the data exporter.

(c) Where permissible under the laws of the country of destination, the data importer agrees to provide the data exporter, at regular intervals for the duration of the contract, with as much relevant information as possible on the requests received (in particular, number of requests, type of data requested, requesting authority/ies, whether requests have been challenged and the outcome of such challenges, etc.).

(d) The data importer agrees to preserve the information pursuant to paragraphs (a) to (c) for the duration of the contract and make it available to the competent supervisory authority on request.

(e) Paragraphs (a) to (c) are without prejudice to the obligation of the data importer pursuant to Clause 14(e) and Clause 16 to inform the data exporter promptly where it is unable to comply with these Clauses.

15.2 Review of legality and data minimisation

(a) The data importer agrees to review the legality of the request for disclosure, in particular whether it remains within the powers granted to the requesting public authority, and to challenge the request if, after careful assessment, it concludes that there are reasonable grounds to consider that the request is unlawful under the laws of the country of destination, applicable obligations under international law and principles of international comity. The data importer shall, under the same conditions, pursue possibilities of appeal. When challenging a request, the data importer shall seek interim measures with a view to suspending the effects of the request until the competent judicial authority has decided on its merits. It shall not disclose the personal data requested until required to do so under the applicable procedural rules. These requirements are without prejudice to the obligations of the data importer under Clause 14(e).

(b) The data importer agrees to document its legal assessment and any challenge to the request for disclosure and, to the extent permissible under the laws of the country of destination, make the documentation available to the data exporter. It shall also make it available to the competent supervisory authority on request.

(c) The data importer agrees to provide the minimum amount of information permissible when responding to a request for disclosure, based on a reasonable interpretation of the request.

SECTION IV – FINAL PROVISIONS

Clause 16 – Non-compliance with the Clauses and termination

(a) The data importer shall promptly inform the data exporter if it is unable to comply with these Clauses, for whatever reason.

(b) In the event that the data importer is in breach of these Clauses or unable to comply with these Clauses, the data exporter shall suspend the transfer of personal data to the data importer until compliance is again ensured or the contract is terminated. This is without prejudice to Clause 14(f).

(c) The data exporter shall be entitled to terminate the contract, insofar as it concerns the processing of personal data under these Clauses, where:

(i) the data exporter has suspended the transfer of personal data to the data importer pursuant to paragraph (b) and compliance with these Clauses is not restored within a reasonable time and in any event within one month of suspension;

(ii) the data importer is in substantial or persistent breach of these Clauses; or

(iii) the data importer fails to comply with a binding decision of a competent court or supervisory authority regarding its obligations under these Clauses.

In these cases, it shall inform the competent supervisory authority of such non-compliance. Where the contract involves more than two Parties, the data exporter may exercise this right to termination only with respect to the relevant Party, unless the Parties have agreed otherwise.

(d) Personal data that has been transferred prior to the termination of the contract pursuant to paragraph (c) shall at the choice of the data exporter immediately be returned to the data exporter or deleted in its entirety. The same shall apply to any copies of the data. The data importer shall certify the deletion of the data to the data exporter. Until the data is deleted or returned, the data importer shall continue to ensure compliance with these Clauses. In case of local laws applicable to the data importer that prohibit the return or deletion of the transferred personal data, the data importer warrants that it will continue to ensure compliance with these Clauses and will only process the data to the extent and for as long as required under that local law.

(e) Either Party may revoke its agreement to be bound by these Clauses where (i) the European Commission adopts a decision pursuant to Article 45(3) of Regulation (EU) 2016/679 that covers the transfer of personal data to which these Clauses apply; or (ii) Regulation (EU) 2016/679 becomes part of the legal framework of the country to which the personal data is transferred. This is without prejudice to other obligations applying to the processing in question under Regulation (EU) 2016/679.

Clause 17 – Governing law

These Clauses shall be governed by the law of one of the EU Member States, provided such law allows for third-party beneficiary rights. The Parties agree that this shall be the law of Luxembourg.

Clause 18 – Choice of forum and jurisdiction

(a) Any dispute arising from these Clauses shall be resolved by the courts of an EU Member State.

(b) The Parties agree that those shall be the courts of Luxembourg.

(c) A data subject may also bring legal proceedings against the data exporter and/or data importer before the courts of the Member State in which he/she has his/her habitual residence.

(d) The Parties agree to submit themselves to the jurisdiction of such courts.

APPENDIX

Annex I

A. LIST OF THE PARTIES:

The Parties mentioned in the Preamble of the Clauses.

B. DESCRIPTION OF TRANSFER

Categories of data subjects whose personal data is transferred:

End users of Viber who elect to communicate with data importer's product.

Categories of personal data transferred:

The personal data transferred concern the following categories of data: Profile photo of user (if exists), unique identifier of user for the unique data importer's product, profile name of user.

Sensitive data transferred (if applicable):

The personal data transferred concern the following categories of sensitive data:

N/A

The frequency of the transfer:

On continuous basis.

Nature of the processing:

Data importer receives the personal data via the Viber API and processes it for the below purpose.

Purpose(s) of the data transfer and further processing

The personal data will be transferred to the data importer to enable personalization of data importer's product.

The period for which the personal data will be retained, or, if that is not possible, the criteria used to determine that period

The period for which the personal data will be retained will be determined by the Data importer accordance with its data privacy and data retention policies.

For transfers to (sub-) processors, also specify subject matter, nature and duration of the processing

N/A

C. COMPETENT SUPERVISORY AUTHORITY

The National Commission for Data Protection of the Grand-Duchy of Luxembourg ("CNPD").

Annex II

TECHNICAL AND ORGANISATIONAL SECURITY MEASURES

In addition to any data security requirements set forth in the Agreement, the data importer shall comply with the following:

Data importer undertakes to implement, maintain, and continuously control and update, appropriate technical and organizational security measures to protect the personal data against accidental or unlawful destruction or accidental loss, alteration, unauthorized disclosure or access, and which provide a level of security appropriate to the risk represented by the processing and the nature of the data to be protected. This includes:

1. Preventing unauthorised persons from gaining access to data processing systems with which personal data are processed or used (physical access control); in particular, by taking the following measures:

  • Controlled access for critical or sensitive areas
  • Video monitoring in critical areas
  • Incident logs
  • Implementation of single entry access control systems,
  • Automated systems of access control,
  • Permanent door and windows locking mechanisms,
  • Key management
  • Permanently manned reception
  • Code locks on doors
  • Monitoring facilities (e.g. alarm device, video surveillance)
  • Logging of visitors
  • Compulsory wearing of ID cards
  • Security awareness training

2. Preventing data processing systems from being used without authorisation (logical access control); in particular, by taking the following measures:

  • Network devices such as intrusion detection systems, routers and firewalls
  • Secure log-in with unique user-ID, password and a second factor for authentication (OTP, MFA, 2FA).
  • Policy mandates locking of unattended workstations. Screensaver password is implemented such that if user forgets to lock the workstation, automatic locking is ensured.
  • Logging and analysis of system usage
  • Role-based access for critical systems containing personal data
  • Process for routine system updates for known vulnerabilities
  • Encryption of laptop hard drives
  • Monitoring for security vulnerabilities on critical systems
  • Deployment and updating of antivirus software
  • individual allocation of user rights, authentication by password and username, use of smartcards for log in, minimum requirements for passwords, password management, password request after inactivity, password protection for BIOS, blocking of external ports (such as USB ports), encryption of data, virus protection and use of firewalls, intrusion detection systems.

3. Ensuring that persons entitled to use a data processing system can gain access only to the data to which they have a right of access, and that, in the course of processing or use and after storage, personal data cannot be read, copied, modified or deleted without authorisation (access control to data); in particular, by taking the following measures:

  • Network devices such as intrusion detection systems, routers and firewalls
  • Secure log-in with unique user-ID, password and a second factor for authentication (OTP, MFA, 2FA).
  • Logging and analysis of system usage
  • Role based access for critical systems containing personal data
  • Encryption of laptop hard drives
  • Deployment and updating of antivirus software
  • Compliance with Payment Card Industry Data Security Standard
  • Definition and management of role based authorization concept, access to personal data only on a need-to-know basis, general access rights only for a limited number of admins, access logging and controls, encryption of data, intrusion detection systems, secured storage of data carriers, secure data lines, distribution boxes and sockets.

4. Ensuring that personal data cannot be read, copied, modified or deleted without authorisation during electronic transmission, transport or storage and that it is possible to verify and establish to which bodies the transfer of personal data by means of data transmission facilities is envisaged (data transfer control); in particular, by taking the following measures:

  • Encryption of communication, tunneling (VPN = Virtual Private Network), firewall, secure transport containers in case of physical transport, encryption of laptops

5. Ensuring that it is possible retrospectively to examine and establish whether and by whom personal data have been inserted into data processing systems, modified or removed (entry control); in particular, by taking the following measures:

  • Logging and analysis of system usage
  • Role based access for critical systems containing personal data
  • Logging and reporting systems, individual allocation of user rights to enter, modify or remove based on role based authorization concept.

6. Ensuring that personal data processed on the basis of a commissioned processing of personal data are processed solely in accordance with the directions of the data exporter (job control); in particular, by taking the following measures:

  • Mandatory security and privacy awareness training for all employees
  • Employee hiring procedures which require the completion of a detailed application form for key employees with access to significant personal data and, where allowed by local law
  • Periodic audits are conducted
  • Implementation of processes that ensure that personal data is only processed as instructed by the data exporter, covering any sub-processors, including diligently selecting appropriate personnel and service providers and monitoring of contract peformance, entering into appropriate data processing agreements with sub-processors, which include appropriate technical and organizational security measures.

7. Ensuring that personal data are protected against accidental destruction or loss (availability control); in particular, by taking the following measures:

  • Backup procedures and recovery systems, redundant servers in separate location, mirroring of hard disks, uninterruptible power supply and auxiliary power unit, remote storage, climate monitoring and control for servers, fire resistant doors, fire and smoke detection, fire extinguising system, anti-virus/firewall systems, malware protection, disaster recovery and emergency plan.

8. Ensuring that data collected for different purposes or different principals can be processed separately (separation control); in particular, by taking the following measures:

  • Internal client concept and technical logical client data segregation, development of a role based authorization concept, separation of test data and live data.

Badge Guidelines

Promote your bot with a Viber badge!

With the Viber badge on your website, emails, communications, ads, promotions and more, you can direct people straight to your bot.

Adding the badge will clearly show your users that you have a bot, and will make it easy for them to subscribe.

Start bringing people to your bot today.

Purple badge White badge
Download Download

Adding the badge

  1. Download a badge to your computer
  2. Paste it in your material/ on your website
  3. Link your bot deep link

Some badges dos and don’ts

The following conditions must be observed when adding the Viber badge to your materials.

  1. Do use the Viber Badges as provided. Don’t alter the badges.
  2. Do make sure there is clear space surrounding the badge equal to one-quarter of the height of the Viber Badges.
  3. Do make the Viber Badge large enough that all of the text is legible.
  4. Do make the Viber Badge the same size or larger than other application store badges.
  5. Do display the Viber Badge on a solid colored background or a simple background image that does not obscure the badge.
  6. Don’t use the Viber Badge for any purpose other than to promote content available on Viber.
  7. Do include the following legal attribution when there is space in the creative: Viber and the Viber logo are trademarks of Viber Media S.a.r.l.

Conditions of Use

By using the Viber Badge, you agree to the terms above and below, the Public Account Guidelines, and all other Viber Policies as well as all other relevant API documentation. The Viber Badge does not allow you to use the Viber trademark and brand in any way not expressly authorized below.

  • Never display a Viber trademark on a site or app that violates the Viber Public Content Policy and/or other Policies.
  • You may not offer or promote prizes or rewards of any kind in exchange for clicking on a Viber Badge.
  • You may not use a Viber Badge to track any data about a user related to the user’s actions or browsing activity, including without limitation whether or not a user clicks on a Viber Badge. This prohibition includes but is not limited to using pixels, cookies, or other methods of recognizing when a user clicks on a Viber Badge.

Glossary

Bots

Bots are fully customizable apps that can interact with users on your behalf. Use the Chat API to learn more about adding a pre-existing bot to an account.

Bot URI

The URI is used for creating a deep link or to share the bot with potential new users. Get your bot URI by placing a call to the get_account_info API method. The URI is part of the response object.

Keyboards

Keyboards are the preferred form for Viber’s bots. Keyboards allow defining the conversation with users by providing answer options to each question. Use the Chat API to add a keyboard to your bot.

Discover

Featured and top partners appear on Discover. Discover is localized, so users will see partners most relevant to them in their country or local area.

Viber API

Viber API

Important notes for bot developers: Please note that since 5.02.24, Viber bots can only be created on commercial terms. Apply for a bot creation and develop a bot using the Chat API. Connect to the API with the token found in your Viber settings.

Authentication token

The authentication token (or application key) is the bot’s unique and secret identifier. The token is used to authenticate requests in the Chat API to prevent unauthorized persons from sending requests on behalf of the bot.

The token is generated when the bot is created, and can be viewed by the bots’s admins in the edit info screen of the bot.


Bot Payment API

Version 1.0
Updated: 16/11/20

IMPORTANT NOTE: this feature is only available for Viber users in Ukraine.

Overview

Use Viber’s Bot Payment API to send an order details message to your bot subscribers, allowing them to make purchases directly from the bot. You will receive the payment status of the transaction in a callback once the user completes the checkout process.

For more information on how to buy from a chatbot on Viber - click here

The use of the Viber’s Bot Payment API is also subject to the Viber Terms & Policies, including the Terms and Conditions regarding Viber Chatbot Payments Service, the Viber Public Account, Public Chat, Bot, Community, and VAP Terms & Guidelines, and the Viber API Terms of Service, as may be amended from time to time.

Definitions

Developer - the party that programs the logic of the bot’s behavior. Development can be done by the merchant or by a third party.

Merchant - entities with a legitimate business activity who sell goods or services. Users purchase goods or services from Merchants.

PSP - A third-party payment service provider that is partnered with Apple and Google to accept payments on the Merchants’ behalf.

Before starting

PSP Account

The Viber Bot Payment API is only available for merchants who have a registered account with one of the following PSPs*:

LiqPay (Ukraine)

Portmone (Ukraine)

IPay (Ukraine)

If you’re a merchant without a chatbot you can contact one of our authorized chatbot developers to help you get started, or develop the chatbot yourself according to the following process and documentation.

*Are you a Payment Service Provider looking to integrate with Viber? Contact us.

Getting Started

  1. Have an active bot - see our step-by-step instructions for creating a bot here.
  2. Enable the payment feature in your bot - contact the relevant PSP and request to enable the payment feature for your bot:

    1. The PSP will make all the necessary checks, sign an agreement with the merchant, approve the request, and reach out to Viber with a request to enable the payments feature for your chatbot.

    2. In the request to Viber, your PSP must include the chatbot URI, your (the chatbot developer) email, and the email of the merchant who owns the chatbot (if it is different to that of the developer).

    3. If Viber approves the request, the payment feature will be enabled on your bot. The merchant, as well as your PSP, will be notified about the approval.

  3. Obtain merchant test and production credentials from your PSP, to be used with Viber’s Bot Payment API. For more information regarding the required credentials from the PSP, please see the Payment Parameters for Payment Type section.
  4. Implement the payment message logic in your chatbot. For further details see the Send Message Request section of Viber’s REST API documentation.
  5. Test your chatbot using the credentials from the PSP and launch once ready.

Once your bot is launched, it will receive a verification mark and will be open for users.

Handling user disputes

In order to enable payments within your chatbot, you must provide support to chatbot users in case they want to dispute a transaction with the merchant. This includes refunds, return/exchange of goods, and any other transaction disputes*.

Channels of support must include:

  • Contact via email - email addresses will be listed in the user support article.

  • Present your support channels as part of the chatbot itself.

*Viber is not responsible for resolving disputes between merchants, PSPs, and users.

API Reference

Important note

The Bot Payment API is currently only supported on mobile devices. When receiving payment messages on Desktop, users will see the message: “I sent you a message that is not supported on your device”.

Architecture

Send Message Request

The send_message API allows bots to send messages to Viber users who have subscribed to the bot. Additional information about send_message requirements and validations can be found here

Please note: The payment message automatically displays a “continue to checkout” button, which expires after 15 minutes.

Resource URL:

https://chatapi.viber.com/pa/send_message

Payment (order details) message structure

Post data

{
 "auth_token":  "445da6az1s345z78-dazcczb2542zv51a-e0vc5fva17480im9",
 "receiver": "01234567890A==",
 "min_api_version": 10,
 "type": "payment",
 "payment":
 {
    "type": "GooglePay",                 
    "description":"2 shirts XL",        
    "total_price": 1.85,                
    "currency_code": "EUR",              
    "payment_parameters":                
    [   
        {"key": "gateway" , "value": "gateway-name"},
        {"key": "gatewayMerchantId", "value": "ExampleMerchantId#123"},
        {"key": "url" , "value": "https://payment-service/api/gateway"},
        {"key": "otherParameterKey", "value": "otherParameterValue"},
	...
    ]
 }
}

Post parameters

Name Description Validation
auth_token A unique bot identifier used to validate your account in all API requests. Once your account is created your authentication token will appear in the account’s “edit info” screen (for admins only). Each request posted to Viber by the account will need to contain the token. Required. Each API request must either include an HTTP header X-Viber-Auth-Token containing the account’s authentication token, or include this parameter in the request body. Each API request must include the account’s authentication token in the HTTP header (X-Viber-Auth-Token), or in the request body.
receiver The unique Viber user ID. Required. the user ID of a subscribed user.
min_api_version The minimum API version required by clients for this message is 10. For more info about min API version click here Optional but highly recommended to ensure that the recipient’s client version supports the payment API.
type Message type. Required. Value: payment.
payment.type Payment type. Required. Currently only “GooglePay” for Android devices and “ApplePay” for iOS devices are valid.
payment.description Free text description. Optional
payment.total_price The price units, up to two decimal places (for example: 1.85). Required
payment.currentcy_code Currency string according to ISO 4217 currency code. Required
payment.payment_parameters List of parameters needed for: Getting the encrypted token for payment system provider (PSP) from the digital wallet platform (currently Google Pay and Apple Pay only). Should be provided by PSP or merchant. Parameters needed for the request to the PSP. Contains a generic array of Json objects, each with “key”-“value” structure. Required

Payment parameters for payment types

The following is a list of parameters that need to be provided to the Google Pay system and to the PSP, in order to process a payment.

Mandatory parameters for PSP Portmone

Key Value Source Description
gateway “portmonecom” PSP PSP ID in Google Pay and Apple Pay systems’
gatewayMerchantId any string Merchant Merchant ID in PSP system
url ”https://www.portmone.com.ua/r3/en/api/gateway/” PSP URL for payment requests to PSP
login any string Merchant Merchant login in PSP system
password any string Merchant Merchant password or token in PSP system*
payeeId any string Merchant Merchant payee ID in PSP system

*The use of a generated password token is preferable but not mandatory. The token will hide your actual password from the request body. You will find the password in the “Personal Area” of the Portmone website or in the Portmone developer’s documentation.

Payment request example for Portmone:

{
	"auth_token": "1234567",
	"min_api_version": 10,
	"receiver": "qwerty",
	"sender":
	{
		"name": "mybot",
		"avatar": ""
	},
	"type": "payment",
	"payment":
	{
		"type":"GooglePay",
		"description":"test payment",
		"total_price":1.23,
		"currency_code":"UAH",
		"payment_parameters":
		[
			{"key":"gateway","value":"portmonecom"},
			{"key":"gatewayMerchantId","value":"12345"},
			{"key":"url","value":"https://www.portmone.com.ua/r3/api/gateway"},
			{"key":"login","value":"login"},
			{"key":"password","value":"PasswordHashCode"},
			{"key":"payeeId","value":"12345"}
		]
	}
}

Mandatory parameters for PSP LiqPay.

Key Value Source Description
gateway “liqpay” PSP PSP ID in Google Pay and Apple Pay systems’
gatewayMerchantId any string Merchant Merchant Public Key in LiqPay PSP system For more info click here
url ”https://www.liqpay.ua/api/viber” PSP URL for payment requests to PSP
data any string Merchant Encrypted data about a purchase. For more info click here
signature any string Merchant Merchant authentication signature in PSP system. For more info click here
payeeId any string Merchant Merchant Public Key in LiqPay PSP system. For more info click here

LiqPay support If you require support in connecting to LiqPay, please contact LiqPay on the LiqPay developers portal for support.

Payment request example for “LiqPay” service

{
	"auth_token": "1234567890&",
	"url": "https://api.webhookinbox.com/i/u9MMDI2ns/in/",
	"min_api_version": 10,
	"receiver": "qwerty",
	"sender":
	{
		"name": "mybot",
		"avatar": ""
	},
	"type": "payment",
	"payment":
	{
		"type":"GooglePay",
		"description":"Test purchase",
		"total_price":9.99,
		"currency_code":"UAH",
		"payment_parameters":
		[
			{"key": "gateway", "value": "liqpay"},
			{"key": "gatewayMerchantId", "value": "abc123"},
			{"key": "url", "value": "https://www.liqpay.ua/api/viber"},
			{"key": "data",	"value": "qwerty12345"},
			{"key": "signature", "value": "123abc"	},
			{"key":"payeeId","value":"abc123"}
		]
	}
}

Mandatory parameters for PSP IPay.ua

Signing algorithm and rest of documentation on iPay.ua website

Key Value Source Description
gateway “ipayua” PSP PSP ID in Google Pay and Apple Pay systems’
gatewayMerchantId any string (example below) Merchant Merchant ID in iPay PSP system
url ”https://api-viber.ipay.ua” PSP URL for payment requests to PSP
subMerchantId any string (example below) Merchant Merchant id in PSP system. Can be found on the PSP website
authSalt any string Merchant Merchant password or token in iPay PSP system. Can be found on the PSP website
authSign any string Merchant Merchant password or token in iPay PSP system. Can be found on the PSP website
transactions any string (example below) Merchant Optional. An array of transactions, as a string, not a JSON array.

Payment request example for IPay.ua

{
  "auth_token": "1234567890&"
  "receiver": "qwerty",
  "min_api_version": 10,
  "type": "payment",
  "payment": {
	"type": "GooglePay",
	"description": "2 shirts XL",
	"total_price": 0.3,
	"currency_code": "UAH",
	"payment_parameters": 
	[
	  {"key": "gateway","value": "ipayua"},
	  {"key": "gatewayMerchantId","value": 1111},
	  {"key": "url","value": "https://api-viber.ipay.ua"},
	  {"key": "subMerchantId","value": 2222},
	  {"key": "authSalt","value": "4ad908f5a74096cdcbcf5a36e03089410ce6811a"},
	  {"key": "authSign","value": "9b4b0cd8c06c9d3f23704b53caadaf41e474cd4ee618ccc2dc796fe1be0d2ff882317ecffafe943cbd03f68fa7c3de333843eb1b3d69b5be7a38f96f949aefb3"},
	  {"key": "transactions","value": "[{\"desc\":\"single transaction\",\"amount\":30}]"}
	]
  }
}

Client_status callback

This callback is sent to the bot’s webhook URL after the user taps on the payment provider (i.e. Google Pay) “Pay” button, in the checkout page.

{
 "event": "client_status",               
 "timestamp": 1457764197627,                    
 "message_token": 4912661846655238145,     
 "chat_hostname": "sn-chat-04",
 "user":
 {
    "id": "01234567890A=",                     
    "name": "John McClane",                       
    "avatar": "https://avatar_url",          	
    "country": "UA",                           
    "language": "ua",                     
    "api_version": 1,                           
  },
 "status": {
     "type": "payment", 
     "code": 0,  
     "supported_psps" : ["bank1", "bank2", "bank3"], 
     "tracking_data": "tracking data"   
   }
}

Callback parameters

Name Description Possible values
event Callback type - which event triggered the callback “Client_status”
timestamp Time of the event that triggered the callback Epoch time
user.id Unique Viber user ID  
user.name User’s Viber name  
user.avatar URL of user’s avatar  
user.country User’s two letter country code ISO ALPHA-2 Code
user.language User’s present phone language ISO 639-1
user.api_version The maximal Viber version that is supported by all of the user’s devices  
message_token Unique ID of the message  
chat_hostname For Viber internal use  
status.type Status type “payment”
status.code Numeric code signifying the result of the payment process  
status.supported_psps A list of supported PSPs  
status.tracking_data Tracking data of the message. See more on tracking_data here  

Error codes

General error codes for the Viber Bot API can be found here. The following error codes are those relevant for the Bot Payment API:

Value Name Description
13 apiVersionNotSupported Will be returned when the recipient’s Viber version does not support the payment API. The message was not delivered to the recipient in this case.
21 unsupportedCountry Will be returned when the recipient’s country is not in a supported country. The message was not delivered to the recipient in this case.
3 badData Will be returned when: The currency code is not ISO 4217. The total_price has an invalid value. The payment ‘type’ is not supported. Currently we support payment types “GooglePay” and “ApplePay”. The message was not delivered to the recipient in this case.
22 paymentUnsuported Will be returned when the payment API has not been enabled for the bot.

Channels Post API

Get ready to automatically post your content to an unlimited audience! Using the API described below you can configure your system to post directly into your Viber Channel.Get started now

Prerequisites

  1. Own a Channel – only Channel super admins can get access to API.

  2. Must be using a version of Viber 17.7 or higher.

  3. Obtain Authentication token.

In order to implement our API, as a channel super admin you will need to obtain an authentication token unique for your Channel. You can do this by entering your Channel’s info screen-> scroll down to “Developer Tools” -> copy token -> use the token for posting via API.

Setting a webhook

Once you have your token you will be able to set your Channel’s webhook. To send messages using this API, it is necessary to set a webhook.

Setting the webhook will be done by calling the set_webhook API with a valid and certified URL. For security reasons only URLs with valid and official SSL certificate from a trusted Certificate Authority will be allowed. This action defines the account’s webhook and the type of events the account wants to be notified about.

Once a set_webhook request is sent Viber will send a callback to the webhook to check its availability. The webhook must reply with status 200 for the request to succeed.

Please Note: Posting to the Channel using the API, or when new messages are posted in the Channel by users will not generate a callback to this webhook.

Destination URL for set_webhook POST request

https://chatapi.viber.com/pa/set_webhook

Post data

{
   "url":"https://my.host.com",
   "auth_token":"your_auth_token"
}

Post parameters

Name Description Validation
url Required. Account webhook URL to receive callbacks & messages from users Webhook URL must use SSL. Note: Viber doesn’t support self signed certificates

Set webhook Response

{ 
   "status":0, 
   "status_message":"ok", 
   "event_types":[ 
      "delivered", 
      "seen", 
      "failed", 
      "subscribed", 
      "unsubscribed", 
      "conversation_started" 
   ] 
}

event_types are deprecated, please ignore

Response parameters

Name Description Validation
status Action result 0 for success. In case of failure – appropriate failure status number. See error codes table for additional information
status_message ok or failure reason Success: ok. Failure: invalidUrl, invalidAuthToken , badData , missingData and failure . See error codes table for additional information

Set webhook callback

For each set_webhook request Viber will send a callback to the webhook URL to confirm it is available. The expected HTTP response to the callback is 200 OK – any other response will mean the webhook request failed. If the webhook is not available the set_webhook response will be status 1: invalidUrl.

Callback data

{ 
   "event":"webhook", 
   "timestamp":1457764197627, 
   "message_token":241256543215 
} 

Callback parameters

Name Description Validation
event Callback type – which event triggered the callback webhook
timestamp Time of the event that triggered the callback Epoch time
message_token Unique ID of the message  

Get Account Info

The get_account_info request will fetch the account’s details as registered in Viber. The account admin will be able to edit most of these details from his Viber client.

The Sender IDs of the Channel superadmins (role “superadmin”) and admins (role “admin”) can be found under the “members” field of the response. Only the superadmins’ ID should be used as the sender ID with this API.

Destination:

https://chatapi.viber.com/pa/get_account_info

Post data

{
   "auth_token":"your_auth_token"
}

Response

{
	"status":0,
	"status_message":"ok",
	"Id":"pa:75346594275468546724",
	"chat_hostname":"Channel name",
	"background":"https://content.cdn.viber.com/backgrounds_v1/Android/800/10000501.jpg",
	"members":[
		{
		"id":"01234567890A=",
		"name": "my name",
		"avatar" :"https://example.com",
		"role":"admin"
		}
	]
}

Sending a message

In order to post to your Channel you will need to send a POST request with the below properties.

Destination URL

https://chatapi.viber.com/pa/post

General send message parameters

The following parameters are available for all message types:

Name Description Validation
from Unique Viber user id Required, valid user id. Your audience will see the sender’s name as the Channel name. Note that Channels Super admins uses Channel name alias by default, you can change this in your Channel settings panel
type Message type Required. Available message types: text, picture, video, file, location, contact, sticker, url

Please Note: All requests should be in JSON format.

Message types

Below is a list of all supported message types with post data examples.

Text message

Post data

{
    "auth_token":"your_auth_token", 
    "from":"your_user_id", 
    "type":"text", 
    "text":"Hello world!" 
}

Post parameters

Name Description Validation
type Message type required.text
text The text of the message required. Max 7000 characters

Picture message

Post data

{  
   "auth_token":"your_auth_token", 
   "from":"your_user_id", 
   "type":"picture", 
   "text":"Picture description", 
   "media":"https://www.images.com/img.jpg", 
   "thumbnail":"https://www.images.com/thumb.jpg" 
} 

Post parameters

Name Description Validation
type Message type required.picture
text Description of the photo. Can be an empty string if irrelevant Required. Max 768 characters
media URL of the image (JPEG) Required. Max size 1 MB. Only JPEG format is supported. Other image formats as well as animated GIFs can be sent as URL messages or file messages. The URL must have a resource with a .jpeg file extension. Example: https://www.example.com/path/image.jpeg
thumbnail URL of a reduced size image (JPEG) Optional. Max size 100 kb. Recommended: 400x400. Only JPEG format is supported

Video message

Post data

{  
   "auth_token":"your_auth_token", 
   "from":"your_user_id", 
   "type":"video", 
   "media":"https://www.images.com/video.mp4", 
   "thumbnail":"https://www.images.com/thumb.jpg", 
   "size":10000, 
   "duration":10 
} 

Post parameters

Name Description Validation
type Message type required.video
media URL of the video (MP4, H264) Required. Max size 50 MB. Only MP4 and H264 are supported
size Size of the video in bytes Required
duration Video duration in seconds; will be displayed to the receiver Optional. Max 180 seconds
thumbnail URL of a reduced size image (JPEG) Optional. Max size 100 kb. Recommended: 400x400. Only JPEG format is supported

File message

Post data

{  
   "auth_token":"your_auth_token", 
   "from":"your_user_id", 
   "type":"file", 
   "media":"https://www.images.com/file.doc", 
   "size":10000, 
   "file_name":"name_of_file.doc" 
} 

Post parameters

Name Description Validation
type Message type required.file
media URL of the file Required. Max size 50 MB. See forbidden file formats for unsupported file types
size Size of the file in bytes Required
file_name Name of the file Required. File name should include extension. Max 256 characters (including file extension). Sending a file without extension or with the wrong extension might cause the client to be unable to open the file

Contact message

Post data

{ 
   "auth_token":"your_auth_token", 
   "from":"your_user_id", 
   "type":"contact", 
   "contact":{ 
      "name":"John Doe", 
      "phone_number":"+12025550164" 
   } 
}

Post parameters

Name Description Validation
type Message type required.contact
contact.name Name of the contact Required. Max 28 characters
contact.phone_number Phone number of the contact Required. Max 18 characters

Location message

Post data

{ 
   "auth_token":"your_auth_token", 
   "from":"your_user_id", 
   "type":"location", 
   "location":{ 
      "lat":"37.7898", 
      "lon":"-122.3942" 
   } 
} 

Post parameters

Name Description Validation
type Message type required.location
location Location coordinates Required. Latitude (±90°) and longitude (±180°) within valid ranges

URL message

Post data

{ 
   "auth_token":"your_auth_token",
   "from":"your_user_id",
   "type":"url",
   "text":"optional text to describe the URL",
   "media":"https://www.website.com/go_here"
} 

Post parameters

Name Description Validation
type Message type required.url
media URL Required. Max 2,000 characters
text Description of the URL Optional. Max 120 characters

Sticker message

Post data

{ 
   "auth_token":"your_auth_token", 
   "from":"your_user_id",  
   "type":"sticker", 
   "sticker_id":46105 
} 

Post parameters

Name Description Validation
type Message type required.sticker
sticker_id URL Unique Viber sticker ID. For examples visit the sticker IDs page

Error Codes

The following error codes will be returned with API responses. The status parameter will include the error code value while the status_message parameter will include the error name or a more specific string describing the error.

Value Name Description
0 ok Success
1 invalidUrl The webhook URL is not valid
2 invalidAuthToken The authentication token is not valid
3 badData There is an error in the request itself (missing comma, brackets, etc.)
4 missingData Some mandatory data is missing
7 publicAccountBlocked The account is blocked
8 publicAccountNotFound The account associated with the token is not a account.
9 publicAccountSuspended The account is suspended
10 webhookNotSet No webhook was set for the account
12 tooManyRequests Rate control breach
other General error General error

Refresh a token

In the event that you need to invalidate the current authentication token and generate a new one, please email your request to devsupport@viber.com with the link to the Channel & the super admin’s phone number.


Chat Extensions

Introduction

A Chat Extension is a Viber bot that allows users to search, interact and share content from within a conversation screen by tapping on the button in the Viber app.

Chat Extensions are available only for IOS and Android devices with Viber version 6.8.7 or higher.

Please note: Chat Extensions are designed to allow selected partners who we work closely with to provide search services for users within chats.

The images, photos, pictures etc. displayed herein are for illustration purposes only.

Glossary

Service

A service is the Chat Extension you are providing. When a user taps on the button, a list of all available services is displayed at the center of the screen.

Hint text

This is a short descriptive text displayed in the input field when the service has been tapped on by a user, guiding the user for their input before entering a text. For example “search for a video”. The hint text is limited to 25 characters including spaces. Hint text is a native field presented by the Viber client and can be localized into any Viber supported language.

Service name

This is the short name of your service displayed under the service’s icon when Chat Extensions is opened by a user. The service name is displayed in any message sent through the service. For example, Sent via <service name>. The service name is limited to 10 characters including spaces.

Service id/uri

This is the account identifier used in all links to the Chat Extension. The id is created from the Chat Extension’s service name, and must be in the Latin alphabet. More about their usage in the deep link section.

Default keyboard

If no query is entered, the keyboard will display default results, for example trending, most recent, last viewed and so on.

Search results

Once a user has sent a search query, navigating between the different services will provide results that are fitted to his search query on the previous service. Results are displayed on the first keyboard sent to the user when the service is chosen.

Inline conversation

An inline conversation with a Chat Extension takes places within the context of a chat between two users or a group conversation.

Create a Chat Extension

  1. Submit a request - Chat Extensions are available only to selected Viber partners ,since we can integrate only a limited number of Chat Extensions in our app. If you’re existing Viber partner and would like to consider developing a chat extension please contact your business account manager at Viber or partners@viber.com

  2. Configure a new bot - Chat Extensions are a type of bot. You will make this bot a Chat Extension by following the steps outlined in the section “Start Development”. To Create the bot itself, please follow these steps:
    1. Go to our admin panel and login using the phone number used with your Viber account.
      • For new partners - contact partners@viber.com
      • For existing partners - user partners dashboard to create a new bot
    2. Select Menu-> Create Bot Account
    3. Fill all required information in the form
    4. Save you authentication token for later use: (looks like 4a11d0412127d47b-25725b610c785d44-f1ed5116412b8e32)
  3. Send us your Chat Extension information - please send your business account manager at Viber the following information:
    1. Chat Extension icon image - should be a 720 X 720 pixels PNG format image file.
    2. Display name - shown in the list of available services when users tap the button. Up to 10 characters including spaces.
    3. Hint text - to be displayed inside the search field. Maximum length of 25 characters (including spaces). Please specify whether it is intended to be in multiple languages, and if so please send the translations if you have them.
    4. List of your developers phone numbers - Will be used to add your Chat Extension to your developers Viber accounts for them to test it (numbers can be of any Viber account that you wish to use for testing).

If you’re sending the information directly to partners@viber.com, please include your bot URI and Viber phone number as well.

Note: after updating the icon and hint text of your bot, you can refresh them on your device by changing the language of your device OS, and then change it back.

For users who open the Chat Extension for the first time, this won’t be necessary, and they will see the latest icon and hint text right away.

Important note for bot developers: Viber’s bot platform is open and free for developers to create bots in our ecosystem. Once you’ve created your bot you are welcome to share it with your Viber contacts or promote it outside Viber on your website or social media channels. Please note that Viber is not responsible for promoting your bot.

Start development

Chat Extensions are based on a similar API to the Viber chat bots. We highly recommend that you familiarize yourselves with the Viber Chat bot API prior to developing your chat extension.

Below are the relevant steps and best practices for developing a chat extension using this API.

Note: If you have development and Production versions of your solution running in parallel, you should create separate bots for each, with a seperate webhook URL as well.

Setting a Webhook

When sending a set_webhook request to https://chatapi.viber.com/pa/set_webhook, to indicate that this solution is a Chat Extension, you must include the is_inline parameter.

After setting the webhook, the Chat Extension will receive a callback with the user’s location each time an Android user opens it. Let us know if you wish to disable this behavior (which also disables the location-picker ActionType). The following parameters must be sent in the set_webhook request body:

Name Description Validation
url required. Account webhook URL to receive callbacks & messages from users Webhook URL must use SSL Note: Viber doesn’t support self signed certificates
is_inline Indication of a Chat Extension true for Chat Extension

REST API set_webhook example

{  
   "url": "https://my.host.com",  
   "is_inline" : true
}

Node.JS API set_webhook example

const bot = new ViberBot({
	authToken: YOUR_AUTH_TOKEN_HERE,
	name: "EchoBot",
	avatar: "https://viber.com/avatar.jpg" /* It is recommended to be 720x720, and no more than 100kb. */
});

bot.setWebhook('https://my.host.com', true);

Python API set_webhook example

from viberbot import Api
from viberbot.api.bot_configuration import BotConfiguration

bot_configuration = BotConfiguration(
	name='PythonSampleChatExtension',
	avatar='https://viber.com/avatar.jpg',
	auth_token='YOUR_AUTH_TOKEN_HERE'
)
viber = Api(bot_configuration)

viber.set_webhook('https://my.host.com', is_inline=True)

Receive search queries from users

Users’ search queries will be received by the Chat Extension as ‘text’ type messages, with the users’ search query being the text of the message.

The message event will be fired when messages arrive. Read more about it on the specific API guide (REST, Node.JS, Python).

Excluding file type, all message types are supported for sending from users to Chat Extensions. These include: text, picture, video, contact, URL and location.

Send keyboards

Chat Extensions are able to send and display keyboard messages. The keyboards are fully customizable and can be created and designed specifically for the Chat Extension’s needs. Please read the following article to learn more about keyboards.

Keyboards you send will appear in the Chat Extension’s results area (under the search field) if the following requirements are met:

  1. The parameter reply_type of the last message event callback that was received by the Chat Extension had the value query. Messages with this reply_type value can be sent in the following ways:
    • When users submit search queries in the Chat Extension
    • When users tap keyboard buttons that have the parameter "ReplyType": "query".
  2. No keyboards were sent after receiving the last message event callback that was received by the Chat Extension.
  3. Message type is keyboard. Please read the following article to learn more about keyboards.
  4. Message body must include the parameters chat_id and receiver. The correct values for these parameters can be found in the following way:
    1. On your mobile, open the Chat Extension, search anything.
    2. Confirm the message with "reply_type": "query" was received by your bot.
    3. In the above request, find the chat_id parameter value, and the receiver parameter value is the value of the requerst’s id parameter.
  5. Less than 2 minutes have passed since the last message event callback that was received by the Chat Extension that had "reply_type": "query".
  6. You have sent less than 5 keyboards to the user since their last interaction wiht the chat extension (interaction is a user tap on keyboard button or a search in the chat extension search field if it is displayed).

Examples of keyboard messages with the above parameters:

REST API keyboard message example

{
   "auth_token": "XXXX",
   "chat_id": "XXXX",
   "receiver":"XXXX",
   "min_api_version": 2,
   "tracking_data": "YOUR_TRACKING_DATA",
   "keyboard":{
      "Type":"keyboard",
      "DefaultHeight":true,
      "Buttons":[
         {
            "ActionType":"reply",
            "ActionBody":"reply to me",
            "Text":"Key text",
            "TextSize":"regular"
         }
      ]
   }
}

Node.JS API keyboard message example

const SAMPLE_KEYBOARD = {
    "receiver": "XXXX",
    "chat_id": "XXXX",
	"Type": "keyboard",
	"Revision": 1,
	"Buttons":[
         {
            "ActionType":"reply",
            "ActionBody":"reply to me",
            "Text":"Key text",
            "TextSize":"regular"
         }
      ]
};

const your_keyboard = new KeyboardMessage(SAMPLE_KEYBOARD, [optionalTrackingData or null], null, null, [minApiVersion, integer above 2]);

bot.on(BotEvents.MESSAGE_RECEIVED, (message, response) => {
	response.send(your_keyboard);
});

Python API keyboard message example

VIBER_GENERAL_KEYBOARD = {
	"Type": "keyboard",
	"Buttons":[
         {
            "ActionType":"reply",
            "ActionBody":"reply to me",
            "Text":"Key text",
            "TextSize":"regular"
         }
      ]
}

message=KeyboardMessage(tracking_data='your_tracking_data', keyboard=VIBER_GENERAL_KEYBOARD)

viber.send_messages(to=receiver, messages=[message], chat_id='XXXX')

Message receipts callbacks

Viber offers message status updates for each message sent, allowing the Chat Extension to be notified when the inline message was delivered to the user’s device (delivered status). The seen callback isn’t sent for keyboard type messages.

Chat Extensions can be accessed by deep links from both within a conversation and from outside Viber. These deep links direct users to specific locations in Chat Extensions.

There are three scenarios within deep links.

Scenario 1: viber://chatex

In this scenario, a user is directed to open the Chat Extensions screen.

From inside a chat they are shown the default screen (either the last selected Chat Extension, or in the case of a first time user, the first Chat Extension in the list).

From outside Viber the forward screen is displayed and the user can choose the contact or group for a conversation. Once in this chat the user is shown the default Chat Extensions screen.

Scenario 2: viber://chatex?service=<URI>

In this scenario the user is directed to a particular service within Chat Extensions.

From inside a chat they are directed to the Chat Extension and shown the Chat Extension’s default results.

From outside Viber the forward screen in displayed and the user can choose the contact or group conversation. Once in this chat, the user is directed to the Chat Extension and shown the default results for this Chat Extension.

Scenario 3: viber://chatex?service=<URI>&search=<search_term>

In this scenario, a user is directed to a particular Chat Extension with a specified search term.

From inside a chat they are directed to the Chat Extension and the results shown will relate to the search query.

From outside Viber the forward screen in displayed and the user can choose the contact or group conversation. Once in this chat, the user is directed to the Chat Extension and the results shown will relate to the search query.

Best practices & How-to’s

Send a default results keyboard

Configure your Chat Extension to send a keyboard on a message event, and if the message reply_type is query and the text parameter is not included in the message object.

Send a search results keyboard

Configure your Chat Extension to send a keyboard on a message event, and if the message reply_type is query and the text parameter is included in the message object. The text parameter’s value is the user’s search query.

Send a message to the chat

You can use the send_message API to send messages to the chat between 2 users, by not including the receiver parameter and including the chat_id parameter in the request. You can find the value of the chat_id parameter in the message callback recieved after the user interacts with keyboards in the chat extension, or types search strings in the chat extension.

You will only be able to send messages into the chat a short time after one of the user in the chat interacted with the chat extension (opened it, searched anything, tapped on any buttons).

To take users back to the chat to see the message that was sent to it, you can implement a keyboard button that minimizes the chat extension by including the button parameter ”ReplyType”:”message”, and let users tap it in order to send the message to the chat and be taken back to the chat immediately.

Detect from which keyboard a message was sent

You can specify the user’s current keyboard in the tracking_data parameter of the keyboard message.

This way, when the user taps a button on a keyboard or rich media that has the tracking_data parameter, the value of tracking_data will be sent with the message to the Chat Extension and allow you to identify the specific button or message the user interacted with.

Example of a keyboard message with the tracking_data parameter:

{
   "auth_token": "XXXX",
   "chat_id": "XXXX",
   "receiver":"XXXX",
   "min_api_version": 2,
   "tracking_data": "YOUR_TRACKING_DATA",
   "type":"keyboard",
   "keyboard":{
      "Type":"keyboard",
      "DefaultHeight":true,
      "Buttons":[
         {
            "ActionType":"reply",
            "ActionBody":"reply to me",
            "Text":"Key text",
            "TextSize":"regular",
            "ReplyType": "query"
         }
      ]
   }
}

Implement a ‘next page’ in the chat extension

To display a keyboard in the Chat Extension in response to a button tap in another keyboard, you should specify "ReplyType": "query" on the button in the first keyboard.

This allows the response from your bot to be displayed in the Chat Extension.

Example of a keyboard message with a button that has the "ReplyType":"query" parameter:

{
    "auth_token": "XXXX",
    "receiver": "XXXX",
    "chat_id": "XXXX",
    "min_api_version": 2,
    "tracking_data": "current_page=main_menu",
    "keyboard": {
        "Buttons": [
            {
                "Columns": 3,
                "Rows": 1,
                "ActionType": "reply",
                "ActionBody": "next_page",
                "Text": "Next Page",
                "Silent": true,
                "ReplyType": "query"
            }
        ]
    }
}

Setting flags

Flags are back-end settings that can modify the functionality of your Chat Extension.

Available flags

RA - Modified Recent logic. Enables recent logic after keyboard activity (default is only after message is sent). By default, a Chat Extension service is added to the “Recents” bar if a user sends a message using that Chat Extension. If this is flag is active, the Chat Extension service will be added to Recents bar right after an interaction with a sent keyboard, and not only when a user sends a message from the Chat Extension.

DS - Disables search. Removes Search button from Chat Extension keyboard. You will still receive a message event callback with "reply_type": "query" when a user taps on the service icon, and can respond to it with a keyboard.

DI - Disables input. Disables input field in Chat Extension keyboard. You will still receive a message event callback with "reply_type": "query" when a user taps on the service icon, and can respond to it with a keyboard.

How to set flags

  1. Use your bot’s authentication token, that you created in step 2 of the above section “Create a Chat Extension”.
  2. Send the following request to https://chatapi.viber.com/pa/set_account_info:
{
"auth_token": "YOUR_AUTH_TOKEN",
"chat_flags":["DI","DS","RA"]
}

The above request will apply all 3 flags (DS DI RA). If you wish to set only some of them, simply include only the ones you need in the chat_flags parameter, or set it to [] to remove all flags.

Notes:

  1. After sending the above request, it will take approximately 5 minutes for the flags to be updated.
  2. To view the effect of the flags, you will need to do one of the following:
    1. Change your device’s language or date.
    2. Ask us to add the Chat Extension’s URI to another device, and then see the changes on that device.
    3. Create an entirely new bot, add the flags to it and ask us to add the new bot’s URI to your number. Then you’ll be able to see the flags’ effect on this new Chat Extension.

Publish your Chat Extension

For further information on how to publish your chat extension for Viber users, please contact us at partners@viber.com


Deeplinks

Bot can have deeplinks to direct users to different parts of the bot.

Deeplinks require specifying the URI of your bot. It can be found in the your bot’s Admin Panel or in the response to the get-account-info API request.

There are three types of deeplink available.

Tapping this type of link will open a conversation with the bot and trigger a conversation started event.

The scheme for this link is:

viber://pa?chatURI=<URI>

Tapping this link will open the bot on the info screen. This deeplink is supported on Android and iOS, and is not supported on Desktop.

The scheme for this link is:

viber://pa/info?uri=<URI>

Additional parameters

The bot is able to accept two additional parameters in the deeplink:

Context

The value of this parameter will be forwarded to the bot under the context parameter in the conversation started callback (see conversation started for additional details). The context will be transferred as a string and has no length limit (up to URL length limit).

Text

The value of this parameter will appear in the text input field when the 1-on-1 chat with the bot is opened by pressing the deeplink. The user will be able to send the text as it is, edit it, or delete it.

A deeplink with context parameter will look as follows:

viber://pa?chatURI=<URI>&context=<Your Context>&text=<Your Text>

Note: Some browsers might have a problem identifying the deeplink. To make sure the link works try sending it as a Viber message and pressing it from within Viber.

Chatbot QR scanner

Introduction

Bot subscribers can scan a QR code using Viber’s native QR scanner and share the scanned data with the bot. This means subscribers don’t need to be redirected to an external browser, allowing for a secure and seamless user journey with fewer steps required to complete the process.

The feature takes advantage of Viber’s existing native QR scanner functionality via a URL scheme and allows for the data to be shared with the bot, which can be utilized for numerous use cases:

  • Scanning a merchant’s QR code to send payment via the bot, e.g. for utility bills.
  • Scanning a QR code upon boarding a bus/metro to pay travel fare.
  • Scanning a QR code to receive promotional codes and discounts.

URL scheme

The URL scheme is:

viber://pa/qr?chatURI=<URI>

There are two possible entry point to the flow that you can provide users with:

  • Implement the deeplink (URL scheme) on your mobile assets – just as you would a regular URL. When tapped, the deeplink will trigger the QR scanning flow. If the user doesn’t have an existing Viber chat with the bot, one will automatically be created. Please note that the link will only work for users who have the Viber app installed on their phone/tablet.
  • Send the deeplink as a message from the bot, or implement it behind a button (as a rich media message or as a keyboard button) with the URL scheme defined as the ActionBody. (See examples below.)

When the user agrees to share the scanned data with the bot, it will trigger a conversation_started event. Note that this is not equal to a subscribed event. The conversation_started event will be fired even if the user is already subscribed to the bot. It’s up to you to decide when you’d like to respond to the conversation_started event and when not, based on the user’s status (subscribed or not).

Limitations

Android: Viber 17.1.0.6 and above.
iOS: Viber 17.2 and above.
Desktop: Not supported.

If a user clicks your deeplink on their computer, they will receive the following message (provided they have Viber for Desktop installed):

User journey

1. The user clicks on an external link (outside of Viber) or on a button in a conversation with the bot.
2. The flow is triggered and Viber’s native QR scanner is activated.
3. Once a QR code is recognized and scanned, the user will see a prompt: “Send QR data to: chatURI ? ”.

  • Cancel: The user will return to the QR scanner camera.
  • Yes: The QR scan data will be sent to the bot as a text message beginning with the prefix “QR Data:”.

We recommend setting the silent flag to true. Otherwise, when the user scans the QR code, a message will be sent to the bot consisting of the URL scheme.

Callback example

When the user sends the scanned data to the bot, the callback will look as follows:

{
  "event": "message",
  "timestamp": 1654676100708,
  "chat_hostname": "SN-CALLBACK-03_",
  "message_token": 5715235489597870374,
  "sender": {
    "id": "jc9HsWTZ2Yf2NkRZ8KcNug==",
    "name": "Michael Brown",
    "avatar": "https://avatar.example.com",
    "language": "en",
    "country": "IL",
    "api_version": 10
  },
  "message": {
    "text": "QR data:\n\nYour electricity bill has been paid. Account no. 10901213, amount paid $39.75",
    "type": "text",
    "tracking_data": "tracking data"
  },
  "silent": false
}

The message type in the callback will be text, even if the scanned QR code represents a file. For example, if the QR code leads to a PDF file, the text parameter will include the file’s URL address and the type parameter will be “text.”

IMPORTANT: You will need to set your bot to recognize the “QR Data:” prefix in order to trigger the appropriate response.

Use case examples

In-chat button (rich media message)

{
   "receiver":"K917PBuvPZmhKfb8Vw3b2Q==",
   "type":"rich_media",
   "min_api_version":7,
   "rich_media":{
      "Type":"rich_media",
      "ButtonsGroupColumns":6,
      "ButtonsGroupRows":1,
      "BgColor":"#1ce783",
      "Buttons":[
         {
            "Columns":6,
            "Rows":1,
            "Silent":"false",
            "ActionType":"open-url",
            "ActionBody":"viber://pa/qr?chatURI=examplebot",
            "Text":"<font color=#ffffff>Scan QR Code Now</font>",
            "TextSize":"large",
            "TextVAlign":"middle",
            "TextHAlign":"middle",
            "Image":"https://i.imgur.com/TePDXXu.png"
         }
      ]
   }
}

Keyboard button

{
   "receiver":"B/dQ7y+3akqZtBBp6Hiy/g==",
   "min_api_version":7,
   "type":"text",
   "text":"To pay your bill, please tap on the button below.",
   "keyboard":{
      "Type":"keyboard",
      "DefaultHeight":false,
      "Buttons":[
         {
            "ActionType":"open-url",
            "ActionBody":"viber://pa/qr?chatURI=examplebot",
            "Text":"<b>Scan QR Code Now</b>",
            "TextSize":"large",
            "TextVAlign":"middle",
            "TextHAlign":"center",
            "BgColor":"#1ce783",
            "Silent":"true"
         }
      ]
   }
}

Data

Please keep in mind that as the bot developer, the code’s functionality is your responsibility, so it will be up to you to generate QR codes that you can parse correctly. Viber is merely providing an easy way for subscribers to scan QR codes and share the data with bots. We highly recommend that you test each code before implementing it, to make sure that it works. We recommend that you keep record of the messages you receive from users, as there is no API to fetch this data again.

Additionally, it’s your responsibility to ensure that your bot is set up to handle unexpected data, such as when a subscriber scans a QR that isn’t related to your bot.


Keyboard Examples

Examples of keyboard layouts.

Restaurants

Smoking / non smoking

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 3,
		"Rows": 2,
		"Text": "<font color=\"#494E67\">Smoking</font><br><br>",
		"TextSize": "medium",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"ActionType": "reply",
		"ActionBody": "Smoking",
		"BgColor": "#f7bb3f",
		"Image": "https: //s12.postimg.org/ti4alty19/smoke.png"
	}, {
		"Columns": 3,
		"Rows": 2,
		"Text": "<font color=\"#494E67\">Non Smoking</font><br><br>",
		"TextSize": "medium",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"ActionType": "reply",
		"ActionBody": "Non smoking",
		"BgColor": "# f6f7f9",
		"Image": "https: //s14.postimg.org/us7t38az5/Nonsmoke.png"
	}]
}

Food types

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><font color=\"#494E67\"><b>ASIAN</b></font>",
		"TextSize": "large",
		"TextHAlign": "center",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "ASIAN",
		"BgColor": "#f7bb3f",
		"Image": "https://s18.postimg.org/9tncn0r85/sushi.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><font color=\"#494E67\"><b>FRENCH</b></font>",
		"TextSize": "large",
		"TextHAlign": "center",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "French",
		"BgColor": "#7eceea",
		"Image": "https://s18.postimg.org/ntpef5syd/french.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><font color=\"#494E67\"><b>MEXICAN</b></font>",
		"TextSize": "large",
		"TextHAlign": "center",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "Mexican",
		"BgColor": "#f6f7f9",
		"Image": "https://s18.postimg.org/t8y4g4kid/mexican.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><font color=\"#494E67\"><b>ITALIAN</b></font>",
		"TextSize": "large",
		"TextHAlign": "center",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "Italian",
		"BgColor": "#dd8157",
		"Image": "https://s18.postimg.org/x41iip3o5/itallian.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><font color=\"#494E67\"><b>INDIE</b></font>",
		"TextSize": "large",
		"TextHAlign": "center",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "Indie",
		"BgColor": "#f6f7f9",
		"Image": "https://s18.postimg.org/wq06j3jkl/indi.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><font color=\"#494E67\"><b>MORE</b></font>",
		"TextSize": "large",
		"TextHAlign": "center",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "More",
		"BgColor": "#a8aaba",
		"Image": "https://s18.postimg.org/ylmyu98et/more_Options.png"
	}]
}

Restaurant listing

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 2,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "Zepras_image",
		"BgColor": "#f6f7f9",
		"Image": "https://s14.postimg.org/pireym5h9/Restaurant01.png"
	}, {
		"Columns": 4,
		"Rows": 2,
		"Text": "<br><b>\u00A0\u00A0ZEPRAS</b><br>\u00A0\u00A0Minimum: 100 \u20BD Delivery: 10 \u20BD<br>\u00A0\u00A012:00 - 23:30<br>\u00A0\u00A0aprox. delivery time: 90 min.<br>\u00A0\u00A0Rating: 4 stars, 760 reviews",
		"TextSize": "regular",
		"TextHAlign": "left",
		"TextVAlign": "top",
		"ActionType": "reply",
		"ActionBody": "Zepras_text",
		"BgColor": "#f6f7f9"
	}, {
		"Columns": 2,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "Giraffa_image",
		"BgColor": "#f6f7f9",
		"Image": "https://s14.postimg.org/otdojdb99/Restaurant02.png"
	}, {
		"Columns": 4,
		"Rows": 2,
		"Text": "<br><b>\u00A0\u00A0Giraffa</b><br>\u00A0\u00A0Minimum: 55 \u20BD Delivery: 10 \u20BD<br>\u00A0\u00A012:00 - 23:45<br>\u00A0\u00A0aprox. delivery time: 120 min.<br>\u00A0\u00A0Rating: 4.5 stars, 1300 reviews",
		"TextSize": "regular",
		"TextHAlign": "left",
		"TextVAlign": "top",
		"ActionType": "reply",
		"ActionBody": "Giraffa_text",
		"BgColor": "#f6f7f9"
	}]

}

Games

Selection

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 1,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "purple_flower",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/fvaegniyf/Game1.png"
	}, {
		"Columns": 1,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "green_flower",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/df8l2t0vr/Game2.png"
	}, {
		"Columns": 1,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "green_mushroom",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/u4a0ypxh3/Game3.png"
	}, {
		"Columns": 1,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "cactus",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/c2vhenstz/Game4.png"
	}, {
		"Columns": 1,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "blue_pink_flower",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/srwxakpfb/Game5.png"
	}, {
		"Columns": 1,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "greenish_flower",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/knot5u307/Game6.png"
	}, {
		"Columns": 6,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "mud",
		"BgColor": "#e0e0e0",
		"Image": "https://s15.postimg.org/huvllt2nr/longbutton.png"
	}]
}

Quiz

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 2,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "salmon",
		"BgColor": "#e0e0e0",
		"Image": "https://s22.postimg.org/es631qrq5/salmon.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "flamingo",
		"BgColor": "#e0e0e0",
		"Image": "https://s22.postimg.org/67crakhjx/flamingo.png"
	}, {
		"Columns": 2,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "snakes",
		"BgColor": "#e0e0e0",
		"Image": "https://s22.postimg.org/r82svhl25/snake.png"
	}]
}

News

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><br><br><br><br>\u00A0\u00A0\u00A0<font color='#ffffff'>Politics</font>",
		"TextHAlign": "left",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "clinton_image",
		"BgColor": "#ffffff",
		"Image": "https://s9.postimg.org/mebu960yz/politics.png"
	}, {
		"Columns": 4,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "clinton_text",
		"BgColor": "#ffffff",
		"Text": "\u00A0\u00A0\u00A0<b>Clinton and Trump Begin <br>\u00A0\u00A0\u00A0 Final Sprint to Election Day </b><br><br>\u00A0\u00A0\u00A0Hillary Clinton \"Allergic\" to Trump<br><br><font color=#999999'>\u00A0\u00A0\u00A01 min. ago</font>",
		"TextHAlign": "left",
		"TextVAlign": "top"
	}, {
		"Columns": 2,
		"Rows": 2,
		"Text": "<br><br><br><br><br>\u00A0\u00A0\u00A0<font color='#ffffff'>Sports</font>",
		"TextHAlign": "left",
		"TextVAlign": "middle",
		"ActionType": "reply",
		"ActionBody": "serena_image",
		"BgColor": "#ffffff",
		"Image": "https://s9.postimg.org/ok653o4ff/sports.png"
	}, {
		"Columns": 4,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "serena_text",
		"BgColor": "#ffffff",
		"Text": "\u00A0\u00A0\u00A0<b>Serena Williams: World No .1 <br>\u00A0\u00A0\u00A0surpasses Federer's record </b><br><br>\u00A0\u00A0\u00A0Wiliams breaks grand slam record<br><br><font color=#999999>\u00A0\u00A0\u00A02 hours ago</font>",
		"TextHAlign": "left",
		"TextVAlign": "top"
	}]
}

E-commerce

{
	"Type": "keyboard",
	"Buttons": [{
		"Columns": 1,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "lotion1",
		"BgColor": "#e0e0e0",
		"Text": "<font color=’#807b78’>5.99 \u20BD</font>",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"Image": "https://s12.postimg.org/484u3tg89/cream_01.png"
	}, {
		"Columns": 1,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "lotion2",
		"BgColor": "#e0e0e0",
		"Text": "<font color=’#807b78’>7.99 \u20BD</font>",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"Image": "https://s12.postimg.org/k7s3141nt/cream_02.png"
	}, {
		"Columns": 1,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "lotion3",
		"BgColor": "#e0e0e0",
		"Text": "<font color=’#807b78’>9.99 \u20BD</font>",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"Image": "https://s12.postimg.org/9m87p3vc9/cream_03.png"
	}, {
		"Columns": 1,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "lotion4",
		"BgColor": "#e0e0e0",
		"Text": "<font color=’#807b78’>12.99 \u20BD</font>",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"Image": "https://s12.postimg.org/5r4tmjc6h/cream_04.png"
	}, {
		"Columns": 1,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "lotion5",
		"BgColor": "#e0e0e0",
		"Text": "<font color=’#807b78’>19.99 \u20BD</font>",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"Image": "https://s12.postimg.org/y5a96ezqh/cream_05.png"
	}, {
		"Columns": 1,
		"Rows": 2,
		"ActionType": "reply",
		"ActionBody": "lotion6",
		"BgColor": "#e0e0e0",
		"Text": "<br><font color=’#807b78’>23.99 \u20BD</font>",
		"TextHAlign": "center",
		"TextVAlign": "bottom",
		"Image": "https://s12.postimg.org/6vyvrwynd/cream_06.png"
	}, {
		"Columns": 6,
		"Rows": 1,
		"ActionType": "reply",
		"ActionBody": "lotion_promotion",
		"BgColor": "#e0e0e0",
		"Text": "<font color=#ffffff>\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0HOLIDAY SEASON SPECIAL OFFERS<br>\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0GET IT NOW FOR ONLY </font><font color=#e897ad>29.99\u20BD</font>",
		"TextHAlign": "left",
		"TextVAlign": "middle",
		"Image": "https://s13.postimg.org/5b8k7118z/image.png"
	}]
}

Keyboards

The Chat Bot API allows sending a custom keyboard with each message, to supply the user with a set of predefined replies or actions. The keyboard can be attached to any message type or sent on its own. Once received, the keyboard will appear to the user instead of the device’s native keyboard. The keyboards are fully customizable and can be created and designed specifically for the bot’s needs.

The client will always display the last keyboard that was sent to it.

Attaching a keyboard to a message

Keyboards can be attached to any message type and be sent and displayed together. To attach a keyboard to a message simply add the keyboard’s parameters to the message JSON.
The keyboard JSON object defines different visual and logic attributes. From the background color, number of buttons and so on.

The example below shows a keyboard sent with a single message.

{
	"keyboard": {
		"DefaultHeight": false,
		"BgColor": "#FFFFFF",
		"Buttons": [{
			"Columns": 6,
			"Rows": 1,
			"BgColor": "#2db9b9",
			"BgMediaType": "gif",
			"BgMedia": "https://www.url.by/test.gif",
			"BgLoop": true,
			"ActionType": "open-url",
			"ActionBody": "www.tut.by",
			"Image": "www.tut.by/img.jpg",
			"Text": "Key text",
			"TextVAlign": "middle",
			"TextHAlign": "center",
			"TextOpacity": 60,
			"TextSize": "regular"
		}]
	}
}

Which in turn will look like this:

General keyboard parameters

Please note: The api level 3 is supported on devices running Viber version 7.6 and above. If you use api level 3 parameters you will have to set the min_api_version parameter on right api level as well.

Name Description Possible values Default value
Buttons required. Array containing all keyboard buttons by order. See buttons parameters below for buttons parameters details    
BgColor optional. Background color of the keyboard Valid color HEX value Default Viber keyboard background
DefaultHeight optional. When true - the keyboard will always be displayed with the same height as the native keyboard.When false - short keyboards will be displayed with the minimal possible height. Maximal height will be native keyboard height true, false false
CustomDefaultHeight optional (api level 3). How much percent of free screen space in chat should be taken by keyboard. The final height will be not less than height of system keyboard 40..70  
HeightScale optional (api level 3). Allow use custom aspect ratio for Carousel content blocks. Scales the height of the default square block (which is defined on client side) to the given value in percents. It means blocks can become not square and it can be used to create Carousel content with correct custom aspect ratio. This is applied to all blocks in the Carousel content 20..100 100
ButtonsGroupColumns optional (api level 4). Represents size of block for grouping buttons during layout 1-6 6
ButtonsGroupRows optional (api level 4). Represents size of block for grouping buttons during layout 1-7 7 for Carousel content ; 2 for Keyboard
InputFieldState optional (api level 4). Customize the keyboard input field. regular- display regular size input field. hidden - hide the input field regular, hidden regular
FavoritesMetadata optional (api level 6). JSON Object, which describes Carousel content to be saved via favorites bot, if saving is available See Favorites Metadata  

Buttons parameters

The following parameters can be defined for each button in the “buttons” array separately. Each button must contain at least one of the following optional parameters: text, BgMedia, image, BgColor.

Name Description Possible values Default value
Columns optional. Button width in columns. See keyboard design for more details 1-6 6
Rows optional. Button height in rows. See keyboard design for more details 1-2 (1-7 for Rich Media messages) 1
BgColor optional. Background color of button Valid color HEX value Default Viber button color
Silent optional. Determine whether the user action is presented in the conversation true/false false
BgMediaType optional. Type of the background media picture, gif. For picture - JPEG and PNG files are supported. Max size: 500 kb picture
BgMedia optional. URL for background media content (picture or gif). Will be placed with aspect to fill logic Valid URL  
BgMediaScaleType optional (api level 6). Options for scaling the bounds of the background to the bounds of this view: crop - contents scaled to fill with fixed aspect. some portion of content may be clipped. fill - contents scaled to fill without saving fixed aspect. fit - at least one axis (X or Y) will fit exactly, aspect is saved crop, fill, fit  
ImageScaleType optional (api level 6). Options for scaling the bounds of an image to the bounds of this view: crop - contents scaled to fill with fixed aspect. some portion of content may be clipped. fill - contents scaled to fill without saving fixed aspect. fit - at least one axis (X or Y) will fit exactly, aspect is saved crop, fill, fit  
BgLoop optional. When true - animated background media (gif) will loop continuously. When false - animated background media will play once and stop true , false true
ActionType optional. Type of action pressing the button will perform. Reply - will send a reply to the bot. open-url - will open the specified URL and send the URL as reply to the bot. See reply logic for more details. Note: location-picker is not supported on desktop, and require adding any text in the ActionBody parameter. ActionType location-picker are not supported for Rich Media messages reply, open-url, location-picker, share-phone, none reply
ActionBody required for ActionTypes reply, share-phone ,open-url and location-picker. Text for reply and URL for open-url. See reply logic for more details For ActionType reply - text For ActionType open-url - Valid URL.  
Image optional. URL of image to place on top of background (if any). Can be a partially transparent image that will allow showing some of the background. Will be placed with aspect to fill logic Valid URL. JPEG and PNG files are supported. Max size: 500 kb  
Text optional. Text to be displayed on the button. Can contain some HTML tags - see keyboard design for more details Free text. Valid and allowed HTML tags. Max 30720 bytes. If the text is too long to display on the button it will be cropped and ended with “…”  
TextVAlign optional. Vertical alignment of the text top, middle, bottom middle
TextHAlign optional. Horizontal align of the text left, center, right center
TextPaddings optional (api level 4). Custom paddings for the text in points. The value is an array of Integers [top, left, bottom, right] per padding 0..12 [12,12,12,12]
TextOpacity optional. Text opacity 0-100 100
TextSize optional. Text size out of 3 available options small, regular, large regular
OpenURLType optional. Determine the open-url action result, in app or external browser internal, external internal
OpenURLMediaType optional. Determine the url media type. not-media - force browser usage. video - will be opened via media player. gif - iOS client will play the gif in full screen mod. picture - client will open the picture in full screen mode not-media , video , gif , picture not-media
TextBgGradientColor optional. Background gradient to use under text, Works only when TextVAlign is equal to top or bottom Hex value (6 characters)  
TextShouldFit optional. (api level 6) If true the size of text will decreased to fit (minimum size is 12) true , false false
TextSize optional. Text size out of 3 available options small, regular, large regular
InternalBrowser optional (api level 3). JSON Object, which includes internal browser configuration for open-url action with internal type See below  
InternalBrowser.ActionButton optional (api level 3). Action button in internal’s browser navigation bar. forward - will open the forward via Viber screen and share current URL or predefined URL. send - sends the currently opened URL as an URL message, or predefined URL if property ActionPredefinedURL is not empty. open-externally - opens external browser with the current URL. send-to-bot - (api level 6) sends reply data in msgInfo to bot in order to receive message. none - will not display any button forward, send, open-externally, send-to-bot, none forward
InternalBrowser.ActionPredefinedURL optional (api level 3). If ActionButton is send or forward then the value from this property will be used to be sent as message, otherwise ignored String with 1 or more characters  
InternalBrowser.TitleType optional (api level 3). Type of title for internal browser if has no CustomTitle field. default means the content in the page’s <OG:title> element or in <title> tag. domain means the top level domain domain, default default
InternalBrowser.CustomTitle optional (api level 3). Custom text for internal’s browser title, TitleType will be ignored in case this key is presented String up to 15 characters  
InternalBrowser.Mode optional (api level 3). Indicates that browser should be opened in a full screen or in partial size (50% of screen height). Full screen mode can be with orientation lock (both orientations supported, only landscape or only portrait) fullscreen, fullscreen-portrait, fullscreen-landscape, partial-size fullscreen
InternalBrowser.FooterType optional (api level 3). Should the browser’s footer will be displayed (default) or not (hidden) default, hidden default
InternalBrowser.ActionReplyData optional (api level 6). Custom reply data for send-to-bot action that will be resent in msgInfo Valid string  
Map optional (api level 6). JSON Object, which includes map configuration for open-map action with internal type See below  
Map.Latitude optional (api level 6). Location latitude (format: “12.12345”) Valid latitude  
Map.Longitude optional (api level 6). Location longitude (format: “3.12345”) Valid longitude  
Frame optional (api level 6). JSON Object. Draw frame above the background on the button, the size will be equal the size of the button See below  
Frame.BorderWidth optional (api level 6). Width of border 0..10 1
Frame.BorderColor optional (api level 6). Color of border Hex color #XXXXXX #000000
Frame.CornerRadius optional (api level 6). The border will be drawn with rounded corners 0..10 0
MediaPlayer optional (api level 6). JSON Object. Specifies media player options. Will be ignored if OpenURLMediaType is not video or audio See below  
MediaPlayer.Title optional (api level 6). Media player’s title (first line) String  
MediaPlayer.Subtitle optional (api level 6). Media player’s subtitle (second line) String  
MediaPlayer.ThumbnailURL optional (api level 6). The URL for player’s thumbnail (background) Valid URL  
MediaPlayer.Loop optional (api level 6). Whether the media player should be looped forever or not true , false false

For example if you would like to open the url in internal browser (min_api_version 3):

{
	"keyboard": {
		"DefaultHeight": true,
		"BgColor": "#FFFFFF",
		"Buttons": [{
			"Columns": 6,
			"Rows": 1,
			"BgColor": "#2db9b9",
			"BgMediaType": "gif",
			"BgMedia": "https://www.url.by/test.gif",
			"BgLoop": true,
			"ActionType": "open-url",
			"OpenURLType": "internal",
			"InternalBrowser": {
				"Mode": "fullscreen",
				"CustomTitle": "Your Title"
			},
			"ActionBody": "www.tut.by",
			"Image": "www.tut.by/img.jpg",
			"Text": "Key text",
			"TextVAlign": "middle",
			"TextHAlign": "center",
			"TextOpacity": 60,
			"TextSize": "regular"
		}]
	}
}

Note: The Silent parameter is supported on devices running Viber version 6.7 and above.

Keyboard design

The keyboard is divided into 6 columns. Each button has a width of 1-6 columns. The client will display the buttons according to the order they were sent in, and will fit as many buttons as possible into each row. If the next button to display can’t be fitted into the current row it will be displayed in the row below. For landscape mode, keyboard’s width will be doubled to 24 columns, and buttons will be displayed according to the same logic. Button height can be 1-2 rows.

Note: keyboards can contain up to 24 rows.

Text design

The buttons’ text can contain some HTML tags for design purposes. The allowed tags are listed in the table below.

Tag Description
<b>X</b> Bold text
<i>X</i> Italic text
<u>X</u> Underlined text
<br> Line break
<s>X</s> Strikethrough text (api level 4)
<font size=”N”>X</font> Custom size N for text block inside the tag (api level 4). Minimum size is 12, maximum size is 32 .
<font color=”#7F00FF”>X</font> Specific text color. Must be a HEX value. Double quotes in JSON should be escaped.

Adding special characters or spaces at the beginning of the row can be done using Unicode. For example, setting a button’s text that starts with a space should look like this:

"Text": "\u00A0 Button text"

Keyboard Reply logic

Pressing a keyboard button would trigger a different reply depending on the buttons “actionType” value.

For ActionType reply:

  • The value of ActionBody is sent as a text message to account (via message event).
  • The value of text appears in the chat thread as message from the user.
  • If no text available, the value of image is used.
  • If no image available, the value of BgMedia is used.
  • If no BgMedia available, the value of BgColor is used.
  • If no BgColor available, the default value of BgColor (white) is used.

For ActionType open-url:

  • The value of ActionBody is sent as a text message to account (via message event).
  • The value of ActionBody is opened in the browser.
  • The value of ActionBody appears in the chat thread as message from the user.

For ActionType share-phone - api level 3 and above:

  • The client will be able to share its phone number via a message callback with a message.contact property that holds the user’s name, phone and avatar.
  • Requires adding any text in the ActionBody parameter.

For ActionType location-picker - api level 3 and above:

  • The client will be able to share their location via a message callback with a message.location property that holds the user’s location.
  • Requires adding any text in the ActionBody parameter.
  • Not supported on desktop, tapping the button will result in a message callback with message.text instead of message.location

For ActionType none:

  • Nothing is sent to the user or account. Just an informative button.

Note: The none action type is supported on devices running Viber version 6.7 and above.

Keyboard design guidelines

You can learn more about keyboard design guidelines in the following spec.

Favorites Metadata

Let the user save your content (gif, link, video) to the user’s favorite extension. Later, when the user enters the favorites extended keyboard and sends an item, the original Carousel content (rich message) will be sent.

The following parameters can help you customize the favorite action:

Name Description Possible values
type required. The type of content you serve gif, link, video
url required. Accessible url of content Valid URL string
title optional. Title for your content Valid string
thumbnail optional. Accessible thumbnail for your content (PNG, JPEG) Valid image (PNG, JPEG) URL string
domain optional. The top domain of your content url Valid string
width optional. Width of your thumbnail image in pixels Integer with positive value
height optional. Height of your thumbnail image in pixels Integer with positive value
alternativeUrl optional. Alternative url for clients with apiVersion < minApiVersion, this will be sent by bot to client, then the client has to send it back Valid URL string
alternativeText optional. Alternative title for the url for clients with apiVersion < minApiVersion, this will be sent by bot to client, then the client has to send it back Valid string

Keyboard examples

Check our examples section for different keyboard use cases.


Viber Share Button

Viber provides a custom URL scheme to help your mobile website visitors share your content via a Viber message.

Sharing (forwarding) a message

To perform this action use the following URL scheme

viber://forward?text=<Your Text>  

How does it work?

With the Viber Share button you can share content directly on Viber.

Once your website user selects the Viber Share button, a predefined text and the current page’s url can be sent to any Viber contact selected by your user.

The user will either be able to edit the text or simply send it without making any changes.

Setting up the Viber Share button

In order to setup the Viber Share button, follow the instructions below:

1. Download Viber Share button kit.
2. Place the following code in the page you want to integrate the Viber Share button:

<a id="viber_share">Click</a>
<script>
    var buttonID = "viber_share";
    var text = "Check this out: ";
    document.getElementById(buttonID)
        .setAttribute('href',"viber://forward?text=" + encodeURIComponent(text + " " + window.location.href));
</script>

3. Choose one of our Viber Share button images and place it on your website within the <a> tag.
4. To change the sharing text, change the text variable:

var text = "Check this out: ";

5. Optional: In case you are already using a viber_share variable on your website, you can change the variable to any ID.

Troubleshooting

  • Avoid using the code inside an iframe.
  • In case the text is longer than 200 characters, it will be trimmed and only the first 200 will be inserted.

Sticker IDs

The following chart shows basic sticker examples and their sticker IDs, for sending to user as a sticker message.

You can find even more stickers by chatting with sticker bot!

Image Sticker ID
40133
40132
40131
40130
40129
40128
40127
40126
40125
40124
40123
40122
40121
40120
40119
40118
40117
40116
40115
40114
40113
40112
40111
40110
40109
40108
40107
40106
40105
40104
40103
40102
40101
40100
40151
40146
40145
40141
40140
40138
40137
40136
40134
114400
114434
114435
114401
114402
114403
114405
114406
114404
114407
114408
114409
114410
114411
114412
114413
114414
114415
114416
114417
114418
114419
114420
114421
114422
114423
114424
114425
114426
114427
114428
114429
114430
114432
114431
114433

Text Formatting

Just like in any Viber chat, you can use text formatting in messages sent from bots.

You can format your message by adding specific markdown characters to any text string using the following markdown guidelines:

Format Markdown                                           String to be sent Appearance on message
Bold One asterisk at each end of the text: * *This text will be bold* This text will be bold
Italics One underscore at each end of the text: _ _This text will be in italics_ This text will be in italics
Monospace Three backticks at each end of the text: ```This text will be in
monospace```
This text will be in monospace
Strikethrough One tilde at each end of the text: ~ ~This text will have a strikethrough ~ This text will have a strikethrough

There must be a space between the last markdown symbol and the next word for the formatting to work. For example:

● *Viber*bots will be *Viber*bots
● *Viber* bots will be Viber bots

If you want to send a message which uses markdown symbols, add a space after the first symbol or before the last symbol to avoid formatting the text. For example:

● *Viber* will be Viber
● * Viber* will be * Viber*

Users can send formatted messages back to the bot. Such messages will be displayed with the markdown symbols in the callback text parameter. For example:

● User sent: Viber
● Callback text will be: *Viber*

Compatibility: Only users with Viber version 14.6 and above will be able to see and send formatting in messages; users with older versions will see the markdowns instead.

Limitations: Markdowns can’t be used in bot keyboards and carousel content messages (rich media messages). If you need to format your text please use HTML tags as described in our Keyboards documentation.