Chatbot API Tutorial

We recently enhanced our API to support interactive WhatsApp messages:
- You can send media and buttons to WhatsApp conversations via button template events
- You can let users choose between a list of up to ten options via list template events
- Bubbles are now supported as clickable buttons on Whatsapp

Introduction

Chatbots can assist your team and take over boring and repetitive tasks such as gathering contact information, allowing your operators to focus on helping customers. They can also be useful as a way to answer simple questions after hours.

Besides using the Chatbot API, you can also write your own chatbot script using the Userlike Bot Language.

This tutorial will walk you through all the details you need to know to integrate a chatbot with our API.

Topic Description
How to set up a chatbot How to configure your chatbot to work with our API
Example chatbot flow What a typical chatbot flow can look like
API overview How our API works
Webhook How our webhook calls are structured
Triggerable events What events you can trigger after receiving webhook calls
Keeping state How to use our API to keep state
Chatbot sessions How chatbot sessions work
Sample Code Sample code for chatbots

Chatbot setup in Userlike

We assume that you already have a chatbot (framework) up and running that you now want to connect to the Userlike chat infrastructure. We also assume that your chatbot (framework) is reachable via HTTP. All you have to do now is to create a "proxy" chatbot in our Dashboard: Think of it as your chatbot's representative (or ambassador) in the Userlike chat infrastructure.

In Userlike, bots are a special type of operator. You can create a new chatbot by going to Unified Messaging Team Chatbots in your Dashboard. Click on **Add chatbot** to create a new chatbot.

Now you can configure your new chatbot:

The first name, last name and operator group settings are identical to those of a regular human operator. The bot type and bot behavior modes are explained below.

Bot type

If you want to create a bot that uses our Bot API, you have to select **API** here. Alternatively you can implement some bot behavior with the Userlike Bot Language.

Bot behavior modes

You can configure your chatbot in four different behavior modes. These modes decide in which situations your contacts will be connected to the chatbot, or whether its human colleagues are the preferred choice.

Bot behavior mode Description
Service time The bot is online only outside of the service time defined on the Widget. During service time, all chats go to your human operators.
Backup The bot is always online but only takes chats when no other operators are available.
Human The bot is always online and takes chats exactly like a normal human operator.
Firewall The bot is always online and receives all conversations (e.g. to categorize and forward them).

After you have configured and saved your new chatbot, it appears in the bot overview, just beneath the human operator table.

From here you can edit it just like any other operator. After you've just added the bot, you need to edit it one time to configure the API settings.

If you edit an existing chatbot, you can additionally configure its API settings, change its profile picture and define how many concurrent chat slots your bot can handle.

Bot conversation timeout

Define a time with no reply from both contact and bot after which the conversation is considered inactive. Once this happens, the bot can perform one of the following actions:

  • **End conversation** and move it to **All conversations**.
  • **Unassign conversation** and move it to the Inbox, where any operator in your group can see and answer it.
  • **Forward conversation** to an available human operator from the same group.

Note that bot conversations don’t show up in your Inbox as long as they’re active. Your operators will only be able to see them once they end, are unassigned or forwarded.

Webhook URL

This is a URL hosted by you, where we can reach your chatbot via HTTP. We will call this endpoint every time a chat-related event happens, e.g. when a conversation starts or when a new message comes in.

API URL

This is a unique URL hosted by Userlike, which your chatbot can reach via HTTP. You can call this endpoint any time your chatbot wants to add something to the conversation that is not a direct response to a previous request made to your webhook.

Webhook URL vs. API URL

So your chatbot has two possibilities to send messages to a conversation:

  • as a direct response to a chat event that has been sent to your **Webhook URL**.
  • as a self-initiated message to your Userlike **API URL**.

In most cases you will just send a response to our calls to your webhook. But when a call makes your chatbot do something that can take a while (like asking another web service), you can acknowledge the request via a response first, and then send the final result to the conversation once it is done.

API security token

You need to generate a security token to use our API endpoint and add it here. Each API call you make needs the token specified as "SECURITY-TOKEN" HTTP Header Field.

Webhook headers

You can specify HTTP Headers that will be included with each webhook request we send to you. You can use this to make sure the requests really originate from us.

Example chatbot flow

Lets say you have a webshop and want to automatically handle some of your customers' requests.

Contact starts a chat

After the bot is set up, you will receive a call to your webhook URL whenever a contact starts a chat with the bot.

Your bot responds to the webhook request directly and sends a welcome text message, together with a bubbles element to offer the contact some choices:

This is how it will look for the contact:

Contact selects delivery status

Once the contact clicks on "Delivery status of an order", you will receive a call to your webhook URL, containing all data from the click event.

Your bot responds by asking the contact for the order ID.

Contact sends order ID

When the contact sends the order ID, you receive another call to your webhook URL.

Since looking up all the delivery information on the order can take a while and requires a call to another webservice, your bot schedules an asynchronous job for it. To inform the contact and not keep them waiting, the bot also sends a short info message as a direct reponse to the webhook call.

Chatbot sends result

After the asynchronous job has finished, the bot makes a self-initiated call to the Userlike "API URL", sending the result of the delivery inquiry.

Your chatbot handled your customer's request automatically, responding to all messages immediately and delivering time-consuming results once they were done.

API Overview

Whenever a contact starts a chat and your bot is selected as a conversation partner, you‘ll receive a webhook call with a `start` event. From then on you will have the `cid` of the chatbot session, which can in turn be used to trigger events.

When the contact writes more messages in the conversation, you will also receive more webhook calls. They will contain the same `cid` as the `start` event has.

To react to incoming events, you can trigger various events yourself. For example you can send a message or forward the conversation to a human. Those events have a similar JSON structure as the incoming ones. To trigger them you can either directly respond to the webhook call, or you can send a request to our chatbot endpoint.

Authentication and Security

We offer to specify HTTP headers when you create or edit your bot in the Dashboard (see Webhook headers), which will be sent with each webhook call. We recommend that you generate a security token and use it in the headers, so you can verify that the webhook calls really originate from us.

To authenticate on our chatbot API endpoint, you have to generate another security token, which you can also enter when you create or edit a bot in the Dashboard (see API security token).

Rate limits

If you use our API endpoint, please note that you can only send 20 requests per minute that use the same `cid`. When the limit is reached, we will respond with 429 status code.

Versioning

Currently we only offer one version of our chatbot API: /v1/

Endpoint URLs without version scheme will always default to the latest version.

Our APIs are constantly evolving, but we are striving to implement any new features in a backwards compatible way. If breaking changes are necessary, we will introduce a new API version. Examples for breaking changes are:

  • Removing, renaming, or moving API entities.
  • Changing or removing functionality.
  • Making optional parameters or properties mandatory.

Non-breaking changes, like new endpoints or new optional properties, can happen anytime.
When we deprecate older versions of the API, we will provide at least 90 days of notice.

Webhook protocol

Whenever certain events happen, you'll receive a POST Request on your webhook, which contains JSON data describing the event.

The event data looks like this. Note that the contact and widget objects were left out to keep the sample shorter. You can find the full object below.

The `info` object contains general information about the chatbot session, while the `packet` object contains event-specific information.

Info object

These are the keys of the `info` object:

Key Type Description
cid String Unique string identifier for the current chatbot session. You will need to include this, if you want to trigger an event in response to the webhook call.
contact Object Information on the contact. If the contact is visiting your site for the first time, this will not contain much. But otherwise this might contain useful information.
context Object You can use the context object to save state for a specific bot session. You can read more about this here: How to use our API to keep state
conversation Object Information about the current conversation, e.g. conversation URL, topic or channel.
approach_mode String The approach mode that was used to start the conversation. It is set to `"proactive"` if the messenger opened automatically, otherwise it is set to `"normal"`.
widget Object Information on the widget that was used to start the conversation.
Webhook Events

Those events can be inside the `packet` object when your webhook is called:

Name Description
start A new chat session with a bot was started. **You should use this event to send a welcome message to the contact.**

Name Type Description
`body` String Optional: The content of the message that the contact sent.
Note: This is usually absent from the event, but in some cases (notably with contacts on messaging apps) it contains the message that initiated the conversation.
message A new message from the contact was received.

Name Type Description
`body` String The content of the message that the contact sent.
media A new file upload from the contact was received.

Name Type Description
`link` String The URL of the uploaded file
Note that the URL is only valid for 15 minutes.
`mime_type` String The MIME type of the uploaded file
click A contact clicked on an option of a bubble or carousel element.

Name Type Description
`option` Integer Index of the option that the contact clicked in the `options` list of the `carousel` or `bubble`. Please note that options are one-indexed, so the first option is referred to by `1`.
`value` Object or string The option that was clicked by the contact. If the click event comes from a bubble element, it contains the clicked option as a string. If the click event comes from a carousel element, it contains the whole option object, with its `headline`, `subheadline` and `media` keys.
forward_failed A forward operation triggered by your bot failed because no operator was available. This is only sent if the `forward_group` or `forward_any` event that your bot sent contained an `on_failure` key set to `feedback`, otherwise the conversation is automatically unassigned and the webhook stops receiving updates.
This event has no payload parameters.
location This is only relevant for WhatsApp. They have a special message that allows users to send a location. If what happens you will get an event of this type.

Name Type Description
`description` str | null Optional description contained in some locations. E.g. if somebody sends a Restaurant, this could contain its name.
`latitude` float Latitude
`longitude` float Longitude
How to respond

We expect you to respond with a 200 status code. You can either leave the response body empty or use the response to directly trigger some events.

Triggerable events

To respond to the events sent to the webhook, you can trigger certain events yourself.

This is what an event looks like:

It always needs a `cid` specified inside the `info`. `packet` also always needs an event name. The `payload` differs for each type of event. In this case we have to provide the content of the message under `body`.

Events can be triggered by two in two ways:

  • You can include a list of event objects as JSON in your response to our webhook call.
  • You can also send the same JSON as a new request to our API endpoint.

Those actions are available:

Name Description
message Send a message to the contact. You can use up to 5,000 characters.

Name Type Required Description
`body` String Yes Content of the message to be sent.
bubbles Send a message to the contact, together with different buttons to click on. You'll receive a click event when the contact clicks on one of the buttons. This works for conversations that started on a website via our chat widget and partially works for WhatsApp and Facebook, but for those we recommend using `list_template` or `button_template`.
If a bubbles message is sent to a contact coming from WhatsApp or Facebook, we automatically try to convert it to an interactive message. For WhatsApp we convert when there ten or less options and each option label has 20 or less characters. Facebook also only allows up to 20 characters in option labels, but they allow up to 13 options. If the bubbles message exceeds the limits, or if the contact wrote via another messaging app, we convert the bubbles to text using the "fallback" parameter.

Name Type Required Description
`body` String Yes Message shown above the options.
`options` List of strings Yes List of all options that the contact should be able to click.
`fallback` String Yes On some messaging channels we cannot display the options as buttons, e.g. WhatsApp or Facebook Messenger. If so, we still show the options, but in a numbered list. Contacts can select them by sending the desired option’s number. In addition, we display this fallback text, which you can use to explain how they select an option.
carousel Similarly to bubbles, but with images on the buttons. You'll receive a click event as a response.

button_template Button template messages are made specifically for certain messaging-apps.
Currently supported messaging-apps are:
- WhatsApp
- Facebook Messenger
They consist of:
- An optional header. For Facebook only images are supported. Whatsapp supports text, an image, a video or a document.
- A message body shown below the header
- An optional footer
- **Up to three buttons**. When the user clicks them, you will receive a click event.
If a button template message is sent to a web-conversation, only the `body` and the options are shown. For not supported messaging apps we currently show a text version.

Name Type Required Restrictions Description
`body` String Yes <= 1024 chars Message shown above the options.
`options` List of objects Yes <= 3 objects List of all options that the contact should be able to click. Each option has to have these keys:
`label` (string): Text shown on the button (20 characters max)
`id` (string): Can be used to recognize the option later. Not visible to the user.
`footer` String No <= 60 chars Text shown below the options.
`header_type` String No text|image|document|video What type of header should be displayed. **Facebook only allows type image**.
`header_text` String No <= 60 chars Text inside the header; only when `header_type` is set to `text`. **Not supported on Facebook**
`header_url` String No Link to media inside the header; only when `header_type` is set to something other than `text`
`fallback` String Yes On some messaging channels we cannot display the options as buttons, e.g. Telegram. If so, we still show the options, but in a numbered list. Contacts can select them by sending the desired option’s number. In addition, we display this fallback text, which you can use to explain how they select an option.


list_template List template messages are made specifically for WhatsApp. They consist of a message with:
- An optional headline text
- A message body shown below the headline
- A button prompting the user to open a selection screen
- A footer shown at the bottom of the message
The selection screen has:
- A headline shown above the options
- A list of **up to ten options**, each has a label and can have an optional description
- A submit button with the same text as the button prompting the select
If a list template message is sent to a non-WhatsApp channel it will still work, but some non-essential parts of the message will be lost.

Name Type Required Restrictions Description
`header` String No <= 60 chars Text shown above the message, before the user clicks to select something.
`body` String Yes <= 1024 chars Message shown before the user clicks to select something.
`button_text` String No <= 20 chars Text on the button prompting the user to select something
`list_header` String No <= 24 chars Text shown above the options in the selection screen.
`options` List of objects Yes <= 10 objects List of all options that the contact should be able to click. Each option has to have those keys:
`label` (string): Main text shown on the list (24 characters max)
`description` (string): Smaller text shown below (72 characters max)
`id` (string): Can be used to recognize the option later. Not visible to the user.
`footer` String No <= 60 chars Text shown below the options in the selection screen.
`fallback` String Yes On some messaging channels we cannot display the options as lists, e.g. WhatsApp or Facebook Messenger. If so, we still show the options, but in a numbered list. Contacts can select them by sending the desired option’s number. In addition, we display this fallback text, which you can use to explain how they select an option.
button (deprecated) Displays a clickable button that opens the provided URL. Note that you will not receive any feedback if the button is clicked. This event is deprecated and will be removed with a future version of the Chatbot API. Please use the buttons event instead.

Name Type Required Description
`body` String Yes Text inside the button.
`link` String Yes Button URL. Note that URLs starting with `file://` and `javascript:` are not allowed.
buttons Displays multiple clickable buttons that open provided URLs. Note that you will not receive any feedback if the button is clicked.

Name Type Required Description
`buttons` Object Yes A list of objects describing the buttons. Each button object needs a "body" and "link" key. "body" is a string that is displayed on the button as text. "link" should be a string that defines the URL to open when contacts click the button.
media Send a message containing an image, video or audio file. Please note that the media pointed to by the URL in `link` must stay reachable from our servers until the request is completely processed. If our systems fail to download your file (due to network outages, for example), you will receive an error response and should take appropriate measures to resolve the situation, e.g. by retrying.

Name Type Required Description
`link` String Yes URL of the media file.
`mime_type` String Yes Mime type of the media file.
navigate Make the contact navigate to a certain URL.

Name Type Required Description
`url` String Yes URL the contact will be navigated to. Note that the target URL must have the same host as the URL the contact is currently visiting.
`fallback` String Yes If the contact’s browser does not allow navigation, this message will be sent to the contact instead. You can use `{{link}}` as a placeholder inside the fallback message, we will replace it with the target URL.
contact_update Update the contact‘s name, email, mobile number, external id and custom fields. You only need to provide one of `name`, `email`, `mobile_number`, `external_customer_id` or `custom_fields`.

Name Type Required Description
`name` String No New contact name.
`email` String No New contact email address.
`mobile_number` String No New contact mobile number. Must be in international format.
`external_customer_id` String No New customer ID.
`custom_fields` Object No Update custom field information for a contact. Object keys should correspond to the IDs of the custom fields you wish to update, while the values represent the new data you want to assign to each respective field on the contact. For more information refer to the "Custom fields" section in the JSON API Tutorial.
abort Stop bot interaction and continue normal conversation flow. The conversation is visible for and can be routed to human operators.
This event has no payload parameters.
end Terminate the bot session and set the 'ended' status on the conversation.
This event has no payload parameters.
forward_group Terminate the bot session and forward the conversation to any available operator from the given group.

Name Type Required Description
`group` String Yes Name of the group the conversation will be assigned to.
`on_failure` String No If set to `"feedback"`, you will receive a `forward_failed` event if no operator is available and the forwarding fails. If this parameter is missing or set to `"unassign"`, the conversation will be unassigned instead.
forward_skills Terminate the bot session and forward the conversation to any available operator who has all of the given skills.

Name Type Required Description
`skills` List of strings Yes List of the names of the required skills.
`on_failure` String No If set to `"feedback"`, you will receive a `forward_failed` event if no operator is available and the forwarding fails. If this parameter is missing or set to `"unassign"`, the conversation will be unassigned instead.
forward_any Terminate the bot session and forward the conversation to any available operator in the same group.

Name Type Required Description
`on_failure` String No If set to `"feedback"`, you will receive a `forward_failed` event if no operator is available and the forwarding fails. If this parameter is missing or set to `"unassign"`, the conversation will be unassigned instead.
delay Delay messages by a specified amount of time. During the delay, contacts will be presented with a typing indicator by default.
Delays only affect subsequent messages in the same response/request, so sending a delay only really makes sense when sent in a list of actions.
Note that a delay doesn’t prevent contacts from sending a message.


Name Type Required Description
`delay` Number Yes The delay in seconds.
`composing` Boolean No If true, contacts will be presented with a typing indicator. Defaults to true.
note_create Create notes during the current conversation. This event can create notes referring to the contact or the conversation. If you set the `contact_identity_id` in the packet’s payload, a note for the contact will be created, otherwise the note will be created for the conversation.


Name Type Required Description
`body` String Yes Note content.
`contact_identity_id` Number No Optional reference to the ID of the contact the note refers to. If omitted, a conversation-based note will be created and appear below the latest message in the conversation’s message history.

Keeping state with the context object

We allow you to keep session-specific state in our API.

On each webhook response or API request, you can provide a `context`, which can be any valid JSON object. Just make sure it’s not bigger than 10 KB.

After you set a context, we will echo the same object in each webhook request we send to you. Note that we will completely overwrite the previous context object, if you provide a new one. If you send us an empty context, we will ignore it and keep the previous one.

Chatbot sessions

Chatbot sessions are started when a conversation is started on your widget, while a bot is configured with a matching behavior mode.

After the session starts, it stays open for a defined timeout without messages or other chat activity. The timeout can be configured in the widget settings under 'Live conversation timeout'.

Right now there is no way to resume an expired session.

Python server example

We prepared a Python sample server for a bot that asks for the contacts name and email, before forwarding him to a human.

This is how the bot interaction looks for a contact: