---
title: Handover API
slug: api/handover
description: Learn how to use the handover functionality in Kindly to seamlessly transition customer support conversations from bots to agents. This document provides a step-by-step guide for requesting and initiating handovers, as well as managing communication betwe
icon: ▪️
docTags: 
createdAt: 2022-05-13T15:40:38.000Z
---

The handover functionality in Kindly allows customer support agents to temporarily replace the bot as the user's conversation partner. From the user's perspective, the conversation with the support agent takes place in the same chat window as the conversation with the bot. While the support agent is in the chat, the bot will not respond to the user's messages, and when the support agent leaves the chat, the bot will return to the conversation.

Support agent handover can be requested by the user by clicking on a handover request button, which can be easily added to a reply like any other button. When a user requests a takover, customer support agents are notified in the platform, and can easily take over the conversation from the *Conversations* section in Kindly. However, if your organization has a customer service center using a different platform, it is possible to set up a connection between your current platform and Kindly to enable handover requests to be handled through your current platform.

As there does not exist a standarized protocol for this kind of functionality, you will need to do some development to create an intermediary service that can talk to both the Kindly API and the customer support platform's API. This document describes the protocol for communication between Kindly and the intermediate service.

*The Handover API was previously named Takeover API, and for backwards compatibility the event names still have these names. The API paths&#x20;*`api/v2/takeover/...`*&#x20;and&#x20;*`api/v2/handover/...`*are aliases for the same functions and you may use either.*

## Architecture suggestions

To handle the communication between Kindly and your customer support platform, Kindly can either communicate directly with the customer support platform or with a intermediary service that forwards messages between the platforms.

### Compatibility application

![](https://api.archbee.com/api/optimize/VLyTaamiYpVSyrmNspQvO/TYvZ3K1BuXH5m-aTrSQJv_architecture-suggestion.png "Architecture suggestion")

### Compatibility plugin

![](https://api.archbee.com/api/optimize/VLyTaamiYpVSyrmNspQvO/KreEVeB9Balz_WNJaC3Oq_compatibility-plugin.png "Architecture suggestion")

## Configuration

You can find the handover configuration page on your workspace under `Settings` --> `Handover`.

![](https://api.archbee.com/api/optimize/VLyTaamiYpVSyrmNspQvO/_jw1pWof64LbpF2Kv-pcU_configuration.png "Handover settings")



1. Select external handover mode
2. Set the webhook URL
3. Get API key
4. Set values for messages & business hours

## Protocol

The protocol is based on HTTP requests between Kindly and your service, where each type of request has a unique `event` name. When Kindly sends events to your service, they will all arrive at your webhook, and your service will have to decide how to handle them based on the `event` specified in the payload.

When you send events from your service to Kindly, you can use different API endpoints for different events. Kindly will respond with a payload that includes an `event` field to confirm that the request was received and that the parameters were valid.

### ➡️ REQUESTING TAKEOVER

When a user clicks on a *request handover* button in the chat, your service will receive a `REQUESTING TAKEOVER` event. Your service should respond with `200 OK` to Kindly, then forward the request to the customer support platform.

:::CodeblockTabs
Example received payload

```json
{
    "event": "REQUESTING TAKEOVER",
    "bot": {
        "id": 123,
        "name": "Test Bot"
    },
    "chat": {
        "_links": {
          "self": "https://bot.kindly.ai/api/v1/chats/5af029421a5ca5141a1ee117"
        },
        "id": "5af029421a5ca5141a1ee117",
        "language": "en",
        "source": "web"
    },
    "user": {
        "id": "53616c7465645f5f463b889c43950414f6e08e05442771013db5d3a3953bcedc4ede6c072f91f90f1c7dee18f232f478"
    }
}
```
:::

### ⬅️ TRANSCRIPT

It is probably useful for the customer service agent to be able to read what the user wrote to the bot and what the bot replied preceding the handover request. To get this info your service can POST to `api/v2/handover/transcript`. The API will respond with  `event: TRANSCRIPT` and contain the message history that you can then show to the agent.

:::CodeblockTabs
Example POST to Kindly

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/transcript \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117"
}'
```
:::

:::CodeblockTabs
Response

```json
{
    "event": "TRANSCRIPT",
    "chat": {
        "id": "5af029421a5ca5141a1ee117",
        "bot_id": 123.
        "messages": [...],
        ...
    }
}
```
:::

### ⬅️ SUMMARIZE

Transcripts can be long and take some time for the agent to read and understand. It's possible to ask Kindly's summarization service to read the chat transcript ahead of the agent joining and provide a short summary of the gist of the conversation. You can POST to `api/v2/handover/summarize`.

To make a summary, the chat has to contain 2 or more user messages that in total contains more than 30 characters.

You can customize the summary generation by adding a "Chat Summary prompt" through the Kindly Platform at this path: `Workspace -> Settings -> Handover`.

:::hint{type="warning"}
The summarization is a call to a large language model that happens on the fly when you make the request. The request may take some time to process, and the result summary text may change between requests. The model is hosted in the EU.
:::

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/summarize \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117"
}'
```

```json
{
    "event": "SUMMARIZED",
    "chat_id": "5af029421a5ca5141a1ee117",
    "summary": "User interacted with the bot using button clicks to request information about pricing, services, and features of Kindly. Bot provided information about Kindly's services, pricing contact process, and customization options, and acknowledged the receipt of user's details."
}
```

### ⬅️ HANDOVER AVAILABILITY

To control whether Kindly should route requests to your Handover system, you can update its **availability status**.

- When the Handover system is *closed*, Kindly will prevent new requests from being sent to it and instead display the relative messages and content from rules for when *Handover is closed*.
- When the Handover system is *open*, Kindly will allow requests and show the relative messages and content from rules for when *Handover is open*.

This could be useful for example if you want to tell us when all your agents are offline or your business hours just started.

Endpoint:

```bash
POST https://bot.kindly.ai/api/v2/handover/availability
```

Expected request body:

```typescript
type requestBody = {
  availability: 'OPEN' | 'CLOSED'
  /** Currently we support only support 1 queue, that should be named 'DEFAULT'. */
  queue: 'DEFAULT' | string,
  /** You should specify the reason of the opening/closure, if possible. */
  reason: 'AGENT_AVAILABILITY' | 'BUSINESS_HOURS' | 'OTHER' 
};
```

Expected response body:

```typescript
type responseBody = {
  event: 'HANDOVER AVAILABILITY UPDATED';
  /** ID of the bot whose handover availability was updated. */
  bot_id: string;
  queue: string; // e.g. 'DEFAULT'
  availability: 'OPEN' | 'CLOSED';
  updated_at: string;
};
```

:::hint{type="warning"}
If you choose to manually manage your *handover availability* through this endpoint, it's your responsibility to open/close it as we don't have any automatic timeout to, for example, re-open your handover after a certain period of closure.
:::

### ⬅️ HANDOVER LIVE TRANSLATION

During handover you can activate live translation of the sent messages. To do so you need to start a handover by POST to `api/v2/handover/start`and pass `sender.language_codes`.

After doing so, the system will check if the chat(client) language matches any of the agents(sender) languages. If not, it will translate each message to the first language from the `language_codes`. Agent messages will be translated to the client(widget)\`s language.

:::CodeblockTabs
Example POST to Kindly

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/start \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117",
    "sender": {
        "name": "Customer support",
        "avatar": "https://ui-avatars.com/api?name=AGENT&size=512",
        "language_codes": ["es", "no", ...]
    },
    "supports_attachment": true
}'
```
:::

### ⬅️ TAKEOVER STARTED

When a customer service agent is ready to enter the chat, your service should POST to `api/v2/handover/start` with the relevant `bot_id` and `chat_id`. If the API key and the IDs are valid, Kindly will respond with `event: TAKEOVER STARTED`. The bot will inform the user that an agent is entering the chat and will no longer respond to the user's messages, until handover is ended by the agent.

The "sender" field is optional and not be displayed in the legacy version of the chat bubble.

Setting the `sender.language_codes` will activate live translation of the sent messages.&#x20;

:::CodeblockTabs
Example POST to Kindly

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/start \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117",
    "sender": {
        "name": "Customer support",
        "avatar": "https://ui-avatars.com/api?name=AGENT&size=512",
        "language_codes": ["es", "no", ...]
    },
    "supports_attachment": true
}'
```
:::

:::CodeblockTabs
Response

```json
{
    "event": "TAKEOVER STARTED",
    "chat_id": "5af029421a5ca5141a1ee117",
    "chatmessage_id": "5af17d2ee9ad1d7d0b3bf03b"
}
```
:::

### ⬅️ TAKEOVER ENDED

When the customer service agent is ready to let the bot take over again, your service should POST to `api/v2/handover/end` with the relevant `bot_id` and `chat_id`. If the API key, and the ids are valid, Kindly will respond with `event: TAKEOVER ENDED`. The bot will inform the user that the agent has left the chat, and will resume responding to the user's messages.

The "sender" field is optional and not be displayed in the legacy version of the chat bubble.

:::CodeblockTabs
Example POST to Kindly

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/end \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117",
    "sender": {
        "name": "Customer support",
        "avatar": "https://ui-avatars.com/api?name=AGENT&size=512"
    }
}'
```
:::

:::CodeblockTabs
Response

```json
{
    "event": "TAKEOVER ENDED",
    "chat_id": "5af029421a5ca5141a1ee117",
    "chatmessage_id": "5af04d54fba4333215e4a3c7"
}
```
:::

### ⬅️ MESSAGE SENT TO USER

Messages from the support platform to the user can be forwarded to the user by POSTing to `api/v2/handover/message/`. In addition to the message, you should also send a name and an avatar in the `sender` field, indicating to the user that the message is from an agent, not from the bot.

Optionally, you can also use `buttons` like in [other API methods](https://docs-v2.kindly.ai/application-api#k-sending-and-receiving), for instance to share a link with the user.

If the POST to Kindly was correct, Kindly will respond with `event: MESSAGE SENT TO USER`.

:::CodeblockTabs
Example POST to Kindly

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/message/ \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117",
    "message": "This is a message from a customer support agent.",
    "sender": {
        "name": "Customer support",
        "avatar": "https://ui-avatars.com/api?name=AGENT&size=512"
    }
}'
```
:::

:::CodeblockTabs
Response

```json
{
    "event": "MESSAGE SENT TO USER",
    "chat_id": "5af029421a5ca5141a1ee117",
    "chatmessage_id": "5af04d48fba4333215e4a3c6"
}
```
:::

### ➡️ MESSAGE FROM USER

When the chat is taken over, and the user sends a message, it will be forwarded to your webhook as a `MESSAGE FROM USER` event. Your service should respond `200 OK` to Kindly, then forward it to the customer support platform.

:::CodeblockTabs
Example received payload

```json
{
    "bot": {
        "id": 123,
        "name": "Test Bot"
    },
    "chat": {
        "_links": {
          "self": "https://bot.kindly.ai/api/v1/chats/5af029421a5ca5141a1ee117"
        },
        "id": "5af029421a5ca5141a1ee117",
        "language": "en",
        "source": "web"
    },
    "event": "MESSAGE FROM USER",
    "message": "hi!",
    "user": {
        "id": "53616c7465645f5f463b889c43950414f6e08e05442771013db5d3a3953bcedc4ede6c072f91f90f1c7dee18f232f478"
    },
    "attachments": [{ "name": "test.jpg", "url": "https://chat.kindlycdn.com/test.jpg", "type": "image/jpeg", "size_kb": 100 }]
}
```
:::

Note: The attachment field will be present only if you have started the handover with the `supports_attachment` field set to `true`.

### ➡️ AGENT TYPING START

In case you want to signal to the widget that the agent is typing, you can do it by using this endpoint: `api/v2/handover/typing_start`. This will display a typing indicator in our widget or SDK.

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/typing_start \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{YOUR_API_KEY}}' \
  --data '{
    "bot_id": {{bot_id}}, 
    "chat_id": "{{chat_id}}",
    "timeout": {{stop_timeout_ms}}
}'
```

To hide this indicator you'll have to use the `typing_stop` endpoint as shown afterwards, or pass a `timeout` field.

In this case Kindly will POST a request to your service as below:

```json
{
    "event": "AGENT TYPING START",
    "chat_id": "{{chat_id}}" // id of the ongoing conversation
}
```

### ➡️ AGENT TYPING STOP

In case you want to signal to the widget that the agent stopped typing, you can do it by using this endpoint: `api/v2/handover/typing_stop`. This will stop displaying a typing indicator in our widget or SDK.

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/typing_stop \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{YOUR_API_KEY}}' \
  --data '{
    "bot_id": {{bot_id}}, 
    "chat_id": "{{chat_id}}"
}'
```

In this case Kindly will POST a request to your service as below:

```json
{
    "event": "AGENT TYPING STOP",
    "chat_id": "{{chat_id}}" // id of the ongoing conversation
}
```

## HMACs

The messages that are sent from Kindly are authenticated using HMACs signed with the same key you use when sending messages to Kindly. See [Webhook signature (HMAC)](docId\:Wi3rDeIS_D7dJWrA_GTm3) for more info about authenticating HMACs.

## System messages

It is also possible to use `api/v2/handover/message/` for other messages than those being forwarded from the customer support agent. For instance, you could have the service tell the user their place in the queue when it changes.

:::CodeblockTabs
Example request

```shell
curl --request POST \
  --url https://bot.kindly.ai/api/v2/handover/message/ \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
    "bot_id": 123,
    "chat_id": "5af029421a5ca5141a1ee117",
    "message": "You are now number 3 in the queue.",
    "sender": {
        "name": "Customer service queue",
        "avatar": "https://ui-avatars.com/api?name=QUEUE&size=512"
    }
}'
```
:::

